退还每位买家的第一,第二和第三个最早购买日期

时间:2014-12-10 12:54:23

标签: sql sql-server row-number partition-by

对于购买者电子邮件地址列表,我试图为每个购买者返回一行,其中包含“1stOrderDate”,“2ndOrderDate”,“3rdOrderDate”和“TotalNumberofOrders”列

我已尝试在子查询的WHERE子句中使用ROW_Number函数,但是它报告WHERE子句中不允许使用Windowed函数,因此我将非常感谢有关如何填写下面的??? s的任何帮助!

SELECT 
PT.email AS 'Email',
MIN(OT.orderdate) AS '1stOrderDate',
???               AS '2ndOrderDate',
???               AS '3rdOrderDate',
COUNT(DISTINCT OT.order_reference) AS 'TotalNumberOfOrders'    

FROM dbo.Orders AS OT
JOIN dbo.Purchaser AS PT ON OT.account_reference = PT.account_reference

GROUP BY PT.Email

1 个答案:

答案 0 :(得分:1)

您可以使用row_number()和条件聚合:

执行此操作
SELECT PT.email,
       MAX(CASE WHEN seqnum = 1 THEN OT.OrderDate END) as OrderDate_1,
       MAX(CASE WHEN seqnum = 2 THEN OT.OrderDate END) as OrderDate_2,
       MAX(CASE WHEN seqnum = 3 THEN OT.OrderDate END) as OrderDate_3,
       COUNT(DISTINCT OT.order_reference) AS TotalNumberOfOrders   
FROM (SELECT o.*, ROW_NUMBER() OVER (PARTITION BY account_reference ORDER BY o.orderdate) as seqnum
      FROM dbo.Orders o
     ) OT JOIN
     dbo.Purchaser PT
     ON OT.account_reference = PT.account_reference
GROUP BY PT.Email

几点说明:

  • 不要使用单引号作为列别名。而是选择不需要转义的列名。
  • 对于segnum = 1逻辑,您可以使用MIN(),但我认为一致性是一个好处。

编辑:

我的猜测是问题是account_referenceemail之间的区别。试试这个:

SELECT email,
       MAX(CASE WHEN seqnum = 1 THEN OT.OrderDate END) as OrderDate_1,
       MAX(CASE WHEN seqnum = 2 THEN OT.OrderDate END) as OrderDate_2,
       MAX(CASE WHEN seqnum = 3 THEN OT.OrderDate END) as OrderDate_3,
       COUNT(DISTINCT OT.order_reference) AS TotalNumberOfOrders   
FROM (SELECT o.*, ROW_NUMBER() OVER (PARTITION BY pt.email ORDER BY o.orderdate) as seqnum
      FROM dbo.Orders o JOIN
           dbo.Purchaser PT
           ON OT.account_reference = PT.account_reference
     ) OT 
GROUP BY PT.Email