2013-02-26 2 views
-4

У меня есть 2 запросов, первый:нужно спросить о связанных querys в SQL Server

SELECT XEDETALLES_BODEGA.IDPROD, SUM(XEDETALLES_BODEGA.CANTIDAD) AS CANTIDAD, MONTH (XEDETALLES_BODEGA.XFECHA) AS MES, 
     YEAR(XEDETALLES_BODEGA.XFECHA) AS ANO, CONVERT(DATETIME, CAST(YEAR(XEDETALLES_BODEGA.XFECHA) AS VARCHAR) + '-1-' + CAST(MONTH(XEDETALLES_BODEGA.XFECHA) AS VARCHAR) , 103) AS FECHA 
FROM XEDETALLES_BODEGA 
    LEFT OUTER JOIN xEGRESOS_BODEGA ON XEDETALLES_BODEGA.IDEGRESO = xEGRESOS_BODEGA.ID 
WHERE (YEAR(XEDETALLES_BODEGA.XFECHA) = 2012) AND XEDETALLES_BODEGA.IDPROD <> 0 
GROUP BY XEDETALLES_BODEGA.IDPROD, MONTH(XEDETALLES_BODEGA.XFECHA), YEAR(XEDETALLES_BODEGA.XFECHA) 
ORDER BY XEDETALLES_BODEGA.IDPROD, MONTH(XEDETALLES_BODEGA.XFECHA), YEAR(XEDETALLES_BODEGA.XFECHA) 

и второй запрос:

SELECT TOP (1) PRECIOUNIT 
FROM XCDETALLES_BODEGA 
WHERE (IDPROD = FIRSTQUERY.IDPROD) AND (XFECHA < FIRSTQUERY.FECHA) 
ORDER BY XFECHA DESC 

Вопрос: Для каждой записи на первом таблице Мне нужно получить PRECIOUNIT в результате второго запроса после замены IDPROD и FECHA.

+5

Измените свой ответ, чтобы удалить ВСЕ CAPS, и используйте редактор кода для форматирования своего кода, чтобы он был читабельным. Верните свой реальный вопрос, чтобы было ясно, что вы просите. –

ответ

0

Возможно, вы, вероятно, выбросите первый запрос в CTE и присоедините его к своему второму запросу.

;WITH 
FIRSTQUERY (IDPROD, CANTIDAD, MES, ANO, FECHA) 
AS 
(
    SELECT XEDETALLES_BODEGA.IDPROD 
    ,SUM(XEDETALLES_BODEGA.CANTIDAD) AS CANTIDAD 
    ,MONTH(XEDETALLES_BODEGA.XFECHA) AS MES 
    ,YEAR(XEDETALLES_BODEGA.XFECHA) AS ANO 
    ,CONVERT(DATETIME, CAST(YEAR(XEDETALLES_BODEGA.XFECHA) AS VARCHAR) + '-1-' + CAST(MONTH(XEDETALLES_BODEGA.XFECHA) AS VARCHAR) , 103) AS FECHA 
    FROM XEDETALLES_BODEGA 
    LEFT OUTER JOIN xEGRESOS_BODEGA ON XEDETALLES_BODEGA.IDEGRESO = xEGRESOS_BODEGA.ID 
    WHERE (YEAR(XEDETALLES_BODEGA.XFECHA) = 2012) AND XEDETALLES_BODEGA.IDPROD <> 0 
    GROUP BY XEDETALLES_BODEGA.IDPROD, MONTH(XEDETALLES_BODEGA.XFECHA),  YEAR(XEDETALLES_BODEGA.XFECHA) 
    ORDER BY XEDETALLES_BODEGA.IDPROD, MONTH(XEDETALLES_BODEGA.XFECHA), YEAR(XEDETALLES_BODEGA.XFECHA) 
) 
SELECT TOP (1) XCDETALLES_BODEGA.PRECIOUNIT 
FROM XCDETALLES_BODEGA 
LEFT JOIN FIRSTQUERY on FIRSTQUERY.IDPROD = XCDETALLES_BODEGA.IDPROD 
WHERE XCDETALLES_BODEGA.XFECHA < FIRSTQUERY.FECHA 
ORDER BY XFECHA DESC 
1

Если вы хотите, чтобы столбец, возвращаемый второго запроса, чтобы быть добавил результатам первого запроса, вы можете просто включить свой второй запрос в первой, как коррелировала подзапрос, как это :

SELECT 
    XEDETALLES_BODEGA.IDPROD, 
    SUM(XEDETALLES_BODEGA.CANTIDAD) AS CANTIDAD, 
    MONTH(XEDETALLES_BODEGA.XFECHA) AS MES, 
    YEAR(XEDETALLES_BODEGA.XFECHA) AS ANO, 
    CONVERT(DATETIME, CAST(YEAR(XEDETALLES_BODEGA.XFECHA) AS VARCHAR) + '-1-' + CAST(MONTH(XEDETALLES_BODEGA.XFECHA) AS VARCHAR), 103) AS FECHA, 
    ( SELECT TOP (1) PRECIOUNIT FROM XCDETALLES_BODEGA WHERE (XCDETALLES_BODEGA.IDPROD = XEDETALLES_BODEGA.IDPROD) AND (XCDETALLES_BODEGA.XFECHA < CONVERT(DATETIME, CAST(YEAR(XEDETALLES_BODEGA.XFECHA) AS VARCHAR) + '-1-' + CAST(MONTH(XEDETALLES_BODEGA.XFECHA) AS VARCHAR), 103)) ORDER BY XCDETALLES_BODEGA.XFECHA DESC ) AS PRECIOUNIT 
FROM XEDETALLES_BODEGA 
    LEFT OUTER JOIN xEGRESOS_BODEGA ON XEDETALLES_BODEGA.IDEGRESO = xEGRESOS_BODEGA.ID 
WHERE (YEAR(XEDETALLES_BODEGA.XFECHA) = 2012) AND XEDETALLES_BODEGA.IDPROD <> 0 
GROUP BY XEDETALLES_BODEGA.IDPROD, MONTH(XEDETALLES_BODEGA.XFECHA), YEAR(XEDETALLES_BODEGA.XFECHA) 
ORDER BY XEDETALLES_BODEGA.IDPROD, MONTH(XEDETALLES_BODEGA.XFECHA), YEAR(XEDETALLES_BODEGA.XFECHA) 
; 

Однако в этом вопросе есть возможности для улучшения.

Прежде всего, я бы представил более короткие псевдонимы таблиц. Просто подумайте над этим переписанием:

SELECT 
    xed.IDPROD, 
    SUM(xed.CANTIDAD) AS CANTIDAD, 
    MONTH(xed.XFECHA) AS MES, 
    YEAR(xed.XFECHA) AS ANO, 
    CONVERT(DATETIME, CAST(YEAR(xed.XFECHA) AS VARCHAR) + '-1-' + CAST(MONTH(xed.XFECHA) AS VARCHAR), 103) AS FECHA, 
    (
    SELECT TOP (1) PRECIOUNIT 
    FROM XCDETALLES_BODEGA AS xcd 
    WHERE (xcd.IDPROD = xed.IDPROD) 
     AND (xcd.XFECHA < CONVERT(DATETIME, CAST(YEAR(xed.XFECHA) AS VARCHAR) + '-1-' + CAST(MONTH(xed.XFECHA) AS VARCHAR), 103)) 
    ORDER BY xcdXFECHA DESC 
) AS PRECIOUNIT 
FROM XEDETALLES_BODEGA AS xed 
    LEFT OUTER JOIN xEGRESOS_BODEGA AS xeg ON xed.IDEGRESO = xeg.ID 
WHERE (YEAR(xed.XFECHA) = 2012) AND xed.IDPROD <> 0 
GROUP BY xed.IDPROD, MONTH(xed.XFECHA), YEAR(xed.XFECHA) 
ORDER BY xed.IDPROD, MONTH(xed.XFECHA), YEAR(xed.XFECHA) 
; 

Согласны ли вы с тем, что более короткие псевдонимы делают ваш запрос более удобочитаемым?

Другой проблемой является ваши критерии группировки, в частности, эти два пункта:

MONTH(xed.XFECHA), YEAR(xed.XFECHA) 

Они, конечно, сделать ваши намерения ясны, но они также испытывают множественные преобразования, как вы делаете их обратно в значение datetime. И теперь мы также используем тот же datetime в коррелированном подзапросе. Эти преобразования абсолютно не нужны, потому что вы можете обойти это наоборот. Вместо того, чтобы извлекать год и месяц из datetime, а затем преобразовать их обратно в datetime, вы можете «округлить» дату и время до начала соответствующего месяца. Следующее выражение делает только что:

DATEADD(MONTH, DATEDIFF(MONTH, 0, xed.XFECHA), 0) 

Теперь, когда вам нужно отобразить месяц и год, как числовые значения, вы можете извлечь их из результата приведенного выше выражения, так как это даст вам тот же самый месяц и год. Итак, взгляните на ваш запрос сейчас:

SELECT 
    xed.IDPROD, 
    SUM(xed.CANTIDAD) AS CANTIDAD, 
    MONTH(DATEADD(MONTH, DATEDIFF(MONTH, 0, xed.XFECHA), 0)) AS MES, 
    YEAR(DATEADD(MONTH, DATEDIFF(MONTH, 0, xed.XFECHA), 0)) AS ANO, 
    DATEADD(MONTH, DATEDIFF(MONTH, 0, xed.XFECHA), 0) AS FECHA, 
    (
    SELECT TOP (1) PRECIOUNIT 
    FROM XCDETALLES_BODEGA AS xcd 
    WHERE (xcd.IDPROD = xed.IDPROD) 
     AND (xcd.XFECHA < DATEADD(MONTH, DATEDIFF(MONTH, 0, xed.XFECHA), 0)) 
    ORDER BY xcd.XFECHA DESC 
) AS PRECIOUNIT 
FROM XEDETALLES_BODEGA AS xed 
    LEFT OUTER JOIN xEGRESOS_BODEGA AS xeg ON xed.IDEGRESO = xeg.ID 
WHERE (YEAR(xed.XFECHA) = 2012) AND xed.IDPROD <> 0 
GROUP BY xed.IDPROD, DATEADD(MONTH, DATEDIFF(MONTH, 0, xed.XFECHA), 0) 
ORDER BY xed.IDPROD, DATEADD(MONTH, DATEDIFF(MONTH, 0, xed.XFECHA), 0) 
; 

Я знаю, о чем вы думаете. Новое выражение, кажется, используется слишком много раз, что не делает запрос очень чистым, тем более, что выражение не так коротки. Может ли это помочь? Да, оно может. Вы можете использовать производную таблицу. Поместите соединения, фильтр WHERE и необходимые столбцы, включая выражение, вычисляющее начало месяца, в подзапрос и пусть ваш основной запрос вытащит данные из него. Оставьте группировку, сортировку и коррелированный подзапрос в главном SELECT. Короче говоря, это то, что вы могли бы в конечном итоге с:

SELECT 
    s.IDPROD, 
    SUM(s.CANTIDAD) AS CANTIDAD, 
    MONTH(s.XFECHA) AS MES, 
    YEAR(s.XFECHA) AS ANO, 
    s.XFECHA, 
    (
    SELECT TOP (1) PRECIOUNIT 
    FROM XCDETALLES_BODEGA AS xcd 
    WHERE (xcd.IDPROD = xed.IDPROD) 
     AND (xcd.XFECHA < s.XFECHA 
    ORDER BY xcd.XFECHA DESC 
) AS PRECIOUNIT 
FROM ( SELECT xed.IDPROD, xed.CANTIDAD, DATEADD(MONTH, DATEDIFF(MONTH, 0, xed.XFECHA), 0) AS FECHA FROM XEDETALLES_BODEGA AS xed LEFT OUTER JOIN xEGRESOS_BODEGA AS xeg ON xed.IDEGRESO = xeg.ID WHERE (YEAR(xed.XFECHA) = 2012) AND xed.IDPROD <> 0 ) s 
GROUP BY s.IDPROD, s.XFECHA 
ORDER BY s.IDPROD, s.XFECHA 
; 

Однако, если вы используете SQL Server 2005 или более поздней версии, вам не нужно производной таблицы - вы можете использовать CROSS ОТНОСИТЬСЯ вместо.Здесь:

SELECT 
    xed.IDPROD 
    SUM(xed.CANTIDAD) AS CANTIDAD, 
    MONTH(s.XFECHA) AS MES, 
    YEAR(s.XFECHA) AS ANO, 
    s.XFECHA, 
    (
    SELECT TOP (1) PRECIOUNIT 
    FROM XCDETALLES_BODEGA AS xcd 
    WHERE (xcd.IDPROD = xed.IDPROD) 
     AND (xcd.XFECHA < s.XFECHA 
    ORDER BY xcd.XFECHA DESC 
) AS PRECIOUNIT 
FROM XEDETALLES_BODEGA AS xed 
    LEFT OUTER JOIN xEGRESOS_BODEGA AS xeg ON xed.IDEGRESO = xeg.ID 
CROSS APPLY ( SELECT DATEADD(MONTH, DATEDIFF(MONTH, 0, xed.XFECHA), 0) AS FECHA ) AS s 
WHERE (YEAR(xed.XFECHA) = 2012) AND xed.IDPROD <> 0 
GROUP BY xed.IDPROD, s.XFECHA 
ORDER BY xed.IDPROD, s.XFECHA 
; 
Смежные вопросы