2016-11-24 7 views
0

AdventureWorks2014 dbを使用して、次のデータを選択します。顧客ごとに、すべての注文を最初の注文から12か月以内に取得したいと考えています。私はその解決策に終わった:SQLグループ化データ

WITH dates AS 
(
SELECT soh.CustomerID 
    ,MIN(soh.OrderDate) AS MinOrderDate 
    ,DATEADD(MONTH, 12, MIN(soh.OrderDate)) as MaxOrderDate 
FROM Sales.SalesOrderHeader soh 
JOIN Sales.SalesOrderDetail sod ON sod.SalesOrderID=soh.SalesOrderID 
GROUP BY soh.CustomerID 
) 

SELECT soh.CustomerID 
    ,soh.OrderDate 
    ,sod.ProductID 
FROM Sales.SalesOrderHeader soh 
JOIN Sales.SalesOrderDetail sod ON sod.SalesOrderID=soh.SalesOrderID 
JOIN dates on dates.CustomerID=soh.CustomerID 
WHERE soh.OrderDate BETWEEN MinOrderDate AND MaxOrderDate 
ORDER BY soh.CustomerID 

これが正しいかどうかわからないのですか?そして、もっと簡単なソリューションが存在するかどうか疑問に思っています。

答えて

1
;WITH cte AS (
    SELECT 
     soh.* 
     ,sod.* 
     ,MIN(soh.OrderDate) OVER (PARTITION BY soh.CustomerId) as MinOrderDate 
    FROM 
     Sales.SalesOrderHeader soh 
     INNER JOIN Sales.SalesOrderDetail sod 
     ON soh.SalesOrderId = sod.SalesOrderId 
) 

SELECT * 
FROM 
    cte 
WHERE 
    OrderDate BETWEEN MinOrderDate AND DATEADD(year,1,MinOrderDate) 

私は彼の日付の比較でOVERではなく)MINを(使用VKPの方法に同意します。私はBETWEENを使用します。これは両方の日付または上位日付を除外する以下のコードを含めたい場合に使用します。私が365の比較に同意しない理由は、うるう年のためです。

OrderDate >= MinOrderDate 
AND OrderDate < DATEADD(year,1,MinOrderDate) 
+0

「soh。*」と「sod。*」は機能しません。カラム名を指定する必要があります。とにかく答えに感謝しています。それは私が知らなかったことです。:) – katta

+0

@katta soh。*とsod。*は少なくとも1つの列名を共有しているためSalesOrderIdは動作しませんでしたが、共通の列名テーブルの間で動作します。 – Matt

+0

OK、ありがとう! – katta

1

これはもう少し簡単だと思います。

ウィンドウ機能は、各顧客の最初の注文日を取得します。次に、顧客ごとに指定された範囲内の注文を選択するだけです。

SELECT customerid,orderdate,productid 
FROM (
SELECT 
soh.*,sod.*, 
MIN(soh.OrderDate) OVER(PARTITION BY soh.CustomerID) AS FirstOrderDate 
FROM Sales.SalesOrderHeader soh 
JOIN Sales.SalesOrderDetail sod ON sod.SalesOrderID=soh.SalesOrderID 
) t 
WHERE DATEDIFF(dd,firstorderdate,orderdate) <= 365