如果您想通過第二查詢返回的是列添加到第一查詢的結果,你可以簡單地將您第二次查詢到的第一個作爲相關子查詢,這樣:
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 APPLY來代替。這裏:
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
;
請編輯您的答案以刪除所有的CAPS,並使用代碼編輯器來格式化您的代碼,使其可讀。改正你的實際問題,讓你的問題更清楚。 – 2013-02-26 20:20:01