SQL分组数据

时间:2016-11-24 17:59:11

标签: sql sql-server

使用AdventureWorks2014数据库,我想选择以下数据:对于每个客户,我希望在第一个订单的12个月内完成所有订单。我最终得到了解决方案:

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 

不确定这是否正确?我想知道是否存在更简单的解决方案?

2 个答案:

答案 0 :(得分:1)

我认为这有点简单。

窗口函数MIN() OVER()为您提供每个客户的第一个订单日期。然后,您只需为每个客户选择指定范围内的订单。

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

答案 1 :(得分: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)

我同意VKP使用MIN()OVER的方法,但不同意他的日期比较。如果您希望它包含两个日期或下面的代码以排除上限日期,我会使用BETWEEN。我不同意365比较的原因是闰年。

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