首页 > 解决方案 > 对单个表中的 2 列使用 STRING_SPLIT

问题描述

我从这样的表开始

ID | City                               | Sales
1  | London,New York,Paris,Berlin,Madrid| 20,30,,50
2  | Istanbul,Tokyo,Brussels            | 4,5,6

可以有无限数量的城市和/或销售。

我需要让每个城市和他们的销售额都有自己的记录。所以我的结果应该是这样的:

ID | City                               | Sales
1  | London                             | 20
1  | New York                           | 30
1  | Paris                              | 
1  | Berlin                             | 50
1  | Madrid                             | 
2  | Istanbul                           | 4 
2  | Tokyo                              | 5
2  | Brussels                           | 6  

到目前为止我得到的是

SELECT ID, splitC.Value, splitS.Value
FROM Table
CROSS APLLY STRING_SPLIT(Table.City,',') splitC
CROSS APLLY STRING_SPLIT(Table.Sales,',') splitS

一次交叉应用,这非常有效。但是当使用第二个查询执行查询时,它开始大量增加记录数(我认为这是有道理的,因为它试图再次拆分每个城市的销售额)。

解决此问题的选择是什么?STRING_SPLIT 不是必需的,这就是我开始的方式。

标签: sql-servertsql

解决方案


STRING_SPLIT没有关于原始位置是什么的上下文。事实上,文档明确指出它并不关心它:

输出的顺序可能会有所不同,因为不能保证顺序与输入字符串中子字符串的顺序相匹配。

因此,您需要使用了解此类基本事物的东西,例如DelimitedSplit8k_LEAD.

然后你可以做这样的事情:

WITH Cities AS(
    SELECT ID,
           DSc.Item,
           DSc.ItemNumber
    FROM dbo.YourTable YT
         CROSS APPLY dbo.DelimitedSplit8k_LEAD(YT.City,',') DSc)
Sales AS(
    SELECT ID,
           DSs.Item,
           DSs.ItemNumber
    FROM dbo.YourTable YT
         CROSS APPLY dbo.DelimitedSplit8k_LEAD(YT.Sales,',') DSs)
SELECT ISNULL(C.ID,S.ID) AS ID,
       C.Item AS City,
       S.Item AS Sale
FROM Cities C
     FULL OUTER JOIN Sales S ON C.ItemNumber = S.ItemNumber;

当然,真正的解决方案是修复您的设计。这种类型的设计将来只会给你带来100个问题。现在修复它,而不是以后;你越早这样做,你就会越早获得这么多的回报。


推荐阅读