2016-11-24 55 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) 

我同意使用MIN(的VKP的方法)OVER但與他的日期比較。如果您希望包含日期或下面的代碼以排除較高日期,我會使用BETWEEN。我不同意365比較的原因是閏年。

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

只是一個小小的評論 - 'soh。*'和'sod。*'不起作用,您需要指定列名稱。無論如何,非常感謝您的答案,這是我不知道的東西:) – katta

+0

@katta soh。*和sod。*,因爲他們共享至少一個列名SalesOrderId它不會工作,但如果沒有共同的列名它會工作的表之間。 – Matt

+0

好了解,謝謝! – 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