2 番目のクエリによって返された列を最初のクエリの結果に追加する場合は、次のように、2 番目のクエリを相関サブクエリとして最初のクエリに組み込むことができます。
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)
;
エイリアスを短くするとクエリが読みやすくなることに同意しますか?
もう 1 つの問題は、グループ化の基準、特に次の 2 つの項目です。
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
;