【问题标题】:Return first element of each cell返回每个单元格的第一个元素
【发布时间】:2022-01-22 08:07:03
【问题描述】:

我有一张这样的桌子:

Id Description Recipient
1 lipsum 35235
2 dolor est 123, 456, 2432
3 Lorem Ipsum 143243, 34, 2344

我想要这样的输出:

Id Description Recipient RecipientId
1 lipsum 35235 35235
2 dolor est 123, 456, 2432 123
3 Lorem Ipsum 143243, 34, 2344 143243

我需要使用收件人 ID 加入一个收件人数据表。值得庆幸的是,行中每个收件人的必要数据都是相同的,所以我只需要一个 ID。我想返回相同的数据,除了收件人列中的每一行只有第一个(甚至只有一个)ID。

我现在的方法是这样的:

SELECT Id,
       Description,
       Recipient,
       MAX(value) as RecipientID
FROM msg 
CROSS APPLY STRING_SPLIT(Recipient, ',')
GROUP BY Id, Description, Recipient

虽然此方法为我提供了一个收件人 ID,然后我可以将其用作键,但由于收件人列可能在一个单元格中包含大于 2k 的 ID 列表,因此需要很长时间。

我尝试了一种 REGEX 解决方案来提取分隔符前面的起始数字集,但我找不到不用作过滤器的方法。

如果 SQL Server 有一个像 MySQL 的 SUBSTRING_INDEX 这样的函数来获取第一个 ID,那就太好了,但它没有。

我怎样才能只返回每个收件人单元格的一个元素而不必执行CROSS APPLY 和聚合?

【问题讨论】:

  • 请查看stackoverflow.com/questions/3653462/… 并规范化您的表格
  • 您可以使用CHARINDEX()SUBSTRING() 来执行此操作,例如CASE WHEN CHARINDEX(',', Recipient) &gt; 0 THEN SUBSTRING(Recipient, 1, CHARINDEX(',', Recipient)-1) ELSE Recipient END - Example on db<>fiddle。但老实说,只需修复您的架构。 SQL 已经具有存储数据列表的理想结构,它们被称为表。存储分隔列表几乎从来都不是正确的解决方案。
  • 我同意架构只需要更新,但我只是一个低级的数据分析师,对如何构建数据库架构没有发言权。我只是负责制作有效的报告。

标签: sql sql-server tsql


【解决方案1】:

您可以按如下方式使用基本字符串函数:

SELECT Id, Description, Recipient,
       SUBSTRING(Receipient + ',', 1, CHARINDEX(',', Recipient + ',') - 1) AS RecipientId
FROM msg;

这个答案使用了一个技巧,在Recipient 的末尾添加一个逗号,这样CHARINDEX 将始终能够找到它。

【讨论】:

  • 我在想办法处理只有一个值的收件人。您在末尾添加逗号的方法比我想出的任何方法都好。
【解决方案2】:
(SELECT TOP value FROM STRING_SPLIT(Recipient, ', ')) as RecipientId

【讨论】:

  • substring_index 是一个mysql 函数,但问题标记为sql-server
  • LIMIT 也不在 SQL Server 中。
【解决方案3】:

也可以使用 Case 语句获得所需的结果

SELECT  [ID],[Description],[Recipient],SUBSTRING([Recipient],0,case CHARINDEX(',',[Recipient])
      when 0 then len([Recipient])
      else  CHARINDEX(',',[Recipient])
      end) AS RecipientID
  FROM [customer].[dbo].[msg ];

一般来说,建议将收件人值存储在具有一对多关系的新表中。每个值都存储在一个新行中,以避免使用分隔符。但是,此查询适用于您的用例

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-21
    • 1970-01-01
    • 1970-01-01
    • 2016-09-30
    • 1970-01-01
    • 1970-01-01
    • 2017-03-29
    相关资源
    最近更新 更多