【问题标题】:How to aggregate repeating fields into seperate colums [duplicate]如何将重复字段聚合到单独的列中[重复]
【发布时间】:2020-12-17 05:05:29
【问题描述】:

以下情况,pos/neg_text 重复:

这是我的反馈表:

id  text-id    pos_text         neg_text       cat_id
1   1          nice people      null           21 
2   1          nice people      null           24 
3   1          nice people      null           27 
4   1          null             cold room      36
5   1          null             cold room      37

我想将所有这些数据放在一行中,例如:

id  text-id    pos_text         neg_text       pos_cat_id       neg_cat_id
1   1          nice people      cold room      "21,24,27"       "36,37"   

我的 SQL 查询应该是什么样子?我正在我的中间件中使用 TypeScript 实现一个算法来解决这个问题,也许有 DB 专家可以用一个简单的 SQL 查询更优雅地解决这个问题。

使用 SQL Server 2008

【问题讨论】:

  • 到目前为止你尝试过什么?为什么它不起作用?或者您查看过哪些现有解决方案,以及您不了解它们的哪些方面?
  • 你使用的是哪个版本的sql-server?
  • 'onice people' 也发生了什么事?
  • 2008 已经完全不受支持一年多了,如果还没有(前一段时间),您真的应该考虑升级路径。
  • @Lonely 你发布的版本与服务器无关,它们是客户端管理工具SSMS的组件

标签: sql sql-server sql-server-2008 string-aggregation


【解决方案1】:

由于使用了这么旧版本的SQL Server,这并不容易。您缺少像 CONCAT 这样的简单工具来进行隐式转换,以及像 STRING_AGG 这样的更新功能,这意味着您需要对表进行 3 次扫描才能实现 1 次扫描完成的工作。

相反,我们需要在这里使用“旧”FOR XML PATH 方法来聚合值,并使用CONVERT 而不是简单的CONCAT(',',sq.catid)。我使用3 作为长度,但您可能需要更长的长度。

WITH YourTable AS(
    SELECT *
    FROM (VALUES(1,1,'nice people',null,21), 
                (2,1,'nice people',null,24), 
                (3,1,'nice people',null,27), 
                (4,1,null,'cold room',36),
                (5,1,null,'cold room',37))V(id,textid,postext,negtext,catid))
SELECT MIN(ID) AS ID,
       textid,
       MAX(postext) AS postext,
       MAX(negtext) AS negtext,
       STUFF((SELECT ',' + CONVERT(varchar(3),sq.catid)
              FROM YourTable sq
              WHERE sq.textid = YT.textid
                AND sq.postext IS NOT NULL
              ORDER BY sq.id
              FOR XML PATH(''),TYPE).value('(./text())[1]','varchar(MAX)'),1,1,'') AS poscatid,
       STUFF((SELECT ',' + CONVERT(varchar(3),sq.catid)
              FROM YourTable sq
              WHERE sq.textid = YT.textid
                AND sq.negtext IS NOT NULL
              ORDER BY sq.id
              FOR XML PATH(''),TYPE).value('(./text())[1]','varchar(MAX)'),1,1,'') AS negtextid
FROM YourTable YT
GROUP BY YT.textid;

db<>fiddle

请注意,这是在较新版本的 SQL 上的简单程度:

SELECT MIN(ID) AS ID,
       textid,
       MAX(postext) AS postext,
       MAX(negtext) AS negtext,
       STRING_AGG(CASE WHEN postext IS NOT NULL THEN catid END,',') WITHIN GROUP (ORDER BY ID) AS poscatid,
       STRING_AGG(CASE WHEN negtext IS NOT NULL THEN catid END,',') WITHIN GROUP (ORDER BY ID) AS negcatid
FROM YourTable
GROUP BY textid;

【讨论】:

  • 它们都不起作用,我已经实现了一个打字稿版本:/
  • “它们都不起作用”我对此表示异议,@Lonely。 db<>fiddle。 “不工作”是什么意思?
  • 也许你是对的,但谢谢你,我不会投入更多时间,因为我已经在 TypeScript 中实现了它。我试图删除我的问题,不能因为有答案。我不想激怒未来的访客。
  • 删除用户花费时间和精力回答的问题会更加激怒用户,@Lonely。
  • 亲爱的@Larnu,你能给我推荐一本像上面那样教我SQL查询的SQL书吗?非常感谢,..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-05
相关资源
最近更新 更多