SQL Server 2012 中的 group_concat 与 ORDER BY 另一列

Posted

技术标签:

【中文标题】SQL Server 2012 中的 group_concat 与 ORDER BY 另一列【英文标题】:group_concat in SQL Server 2012 with ORDER BY another column 【发布时间】:2012-11-12 17:39:56 【问题描述】:

我有一个包含大约一百万个这样的条目的表:

customer_id | purchased_at     | product
1           | 2012-06-01 00:00 | apples
1           | 2012-09-02 00:00 | apples
1           | 2012-10-01 00:00 | pears
2           | 2012-06-01 00:00 | apples
2           | 2012-07-01 00:00 | apples
3           | 2012-09-02 00:00 | pears
3           | 2012-10-01 00:00 | apples
3           | 2012-10-01 01:00 | bananas

我想将产品连接到一行,DISTINCT 并按照购买的顺序

mysql 中我只使用

select customer_id, min(purchased_at) as first_purchased_at, 
group_concat(DISTINCT product order by purchased_at) as all_purchased_products
from purchases group by customer_id;

得到

customer_id | first_purchased_at | all_purchased_products
1           | 2012-06-01 00:00 | apples, pears
2           | 2012-06-01 00:00 | apples
3           | 2012-09-02 00:00 | pears, apples, bananas

如何在 SQL Server 2012 中做到这一点?

我尝试了下面的“hack”,它有效,但它有点过头了,在长桌子上表现不佳

select
customer_id,
min(purchased_at) as first_purchased_at,
stuff ( ( select  ',' +  p3.product 
          from (select  p2.product, p2.purchased_at, 
          row_number() over(partition by p2.product order by p2.purchased_at) as seq
          from  purchases p2 where
          p2.customer_id = p1.customer_id ) p3 
          where p3.seq = 1 order by p3.purchased_at
          for XML PATH('') ), 1,1,'') AS all_purchased_products  
from purchases p1
group by customer_id;

我能做些什么来解决这个问题?

【问题讨论】:

【参考方案1】:

我不确定这是否会更快,但这里有一个替代版本,您不会在 purchases 中加入两次 STUFF()

select customer_id,
  min(purchased_at) as first_purchased_at,
  stuff ((select ',' +  p2.product 
          from
          (
            select product, customer_id,
                ROW_NUMBER() over(partition by customer_id, product order by purchased_at) rn,
                ROW_NUMBER() over(partition by customer_id order by purchased_at) rnk   
            from purchases
          ) p2 
          where p2.customer_id = p1.customer_id
            and p2.rn = 1
          group by p2.product, rn, rnk
          order by rnk
          for XML PATH('') ), 1,1,'') AS all_purchased_products  
from purchases p1
group by customer_id;

见SQL Fiddle with Demo

结果:

| CUSTOMER_ID |               FIRST_PURCHASED_AT | ALL_PURCHASED_PRODUCTS |
---------------------------------------------------------------------------
|           1 |      June, 01 2012 00:00:00+0000 |           apples,pears |
|           2 |      June, 01 2012 00:00:00+0000 |                 apples |
|           3 | September, 02 2012 00:00:00+0000 |   pears,apples,bananas |

【讨论】:

有点矫枉过正,但这是可能服务器不支持STRING_AGG()时唯一的解决方案,这应该是公认的答案。 谢谢。这对我来说非常有效,并解释了我一直对递归 CTE 的许多问题。在敲了两天之后,我能够使用 Fiddler 来调整你的 SQL 以适应我的 SQL,然后将它用于我更大的查询中。

以上是关于SQL Server 2012 中的 group_concat 与 ORDER BY 另一列的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server UDF 数组输入和输出

sql server 2012中的表分区不完整

如何在没有附加查询的情况下在 SQL Server 中连接没有子查询的 GROUP BY 子句中的字符串?

从多个表中创建 Sql Server VIEW GROUPing BY,选择子查询作为别名

sqlserver2008,sql编程,group by 用法

SQL Server 错误中的 GROUP_CONCAT