根据位置和定界符分割字符串

时间:2020-02-06 06:38:39

标签: sql-server tsql delimiter charindex patindex

我需要帮助。 有关CHARINDEX,PATINDEX,SUBSTRING,LEFT和RIGHT上的SQL的问题。

我有一些字符串需要根据位置和定界符进行拆分。使用其中一些作为列名,另一部分作为数据。并根据行ID对其进行分组。然后根据需要对这些值求和。

样本数据,ID,字符串

1    20:4:10:1:20:3:
2    20:1:
3    10:3:
4    30:4:40:1:50:3:

所需的结果是

id  10  20  30  40  50
1   1   7
2       1
3   3
4           4   1   3

数据:

CREATE TABLE #Split (ID int, SplitString varchar(450))
Insert into #Split (ID, SplitString) values 
(1, '20:4:10:1:20:3:'),
(2, '20:1:'),
(3, '10:3:'),
(4, '30:4:40:1:50:3:')

select * From #Split
DROP TABLE #Split

任何帮助将不胜感激!

数据也可能是这样的:

CREATE TABLE #Split (ID int, String1 varchar(10),  String1Quantity int, String2 varchar(10), String2Quantity int, String3 VARCHAR(10), String3Quantity int, String4 varchar(10), String4Quantity int, String5 varchar(10), String5Quantity int)

Insert into #Split (ID, String1, String1Quantity, String2, String2Quantity, String3, String3Quantity, String4, String4Quantity, String5, String5Quantity) values 
(1,'20',4,'10',1,'20',3, null, null, null, null),
(2,'20',1,null,null,null,null, null, null, null, null),
(3,'10',3,null,null,null,null, null, null, null, null),
(4,'30',4,'40',1,'50',3, null, null, null, null)

select * From #Split


DROP TABLE #Split

2 个答案:

答案 0 :(得分:1)

首先,正如我在评论中所写:解决方案是修复损坏的数据模型。有关更多信息,请阅读Is storing a delimited list in a database column really that bad?,您将在这里看到很多答案,为什么这个问题的答案是绝对是!

话虽这么说,但我知道很多时候,由于许多不同的原因,改变数据库结构是不可行的,即使这样做可以解决许多问题。

现在,基于您的字符串操作函数,我假设您正在使用SQL Server(请注意,对于每个sql问题,您都应始终指定rdbms和版本,如果确实需要,请使用跨数据库解决方案)。

因此,根据您的假设,您最好的选择是使用Jeff Moden's DelimitedSplit8K UDF将字符串分成表格。
此函数将返回一个包含两列的表-一列用于子字符串,一列用于其在源字符串中的索引-这正是开始构造要获取的结果所需要的。

因此,基于该功能,几个常见的表表达式,数据透视表和条件聚合,我想出了以下解决方案:

WITH CTE1 AS
(
    SELECT  Id,
            CAST(IIF(ItemNumber % 2 = 0, Item, NULL) as int) As Data, 
            IIF(ItemNumber % 2 = 1, Item, NULL) As Name, 
            IIF(ItemNumber % 2 = 0, ItemNumber - 1, ItemNumber) As PairNumber
    FROM  #Split
    CROSS APPLY dbo.DelimitedSplit8K(SplitString, ':')
    WHERE Item IS NOT NULL
    AND Item <> ''
), CTE2 AS
(
    SELECT Id, PairNumber, MAX(Data) As Data, MAX(Name) As Name
    FROM CTE1
    GROUP BY Id, PairNumber
)

, CTEPivot AS
(
    SELECT Id, [10], [20], [30], [40], [50]
    FROM 
    (
    SELECT Id, SUM(Data) As Data, Name
    FROM CTE2 
    GROUP BY Id, Name
    ) D
    PIVOT  
    (  
    AVG(Data) 
    FOR Name IN ([10], [20], [30], [40], [50])  
    ) AS PivotTable
)

SELECT  Id, 
        MAX([10]) As [10], 
        MAX([20]) As [20], 
        MAX([30]) As [30], 
        MAX([40]) As [40], 
        MAX([50]) As [50] 
FROM CTEPivot
GROUP BY Id;  

结果:

+----+----+----+----+----+----+
| Id | 10 | 20 | 30 | 40 | 50 |
+----+----+----+----+----+----+
| 1  | 1  | 7  |    |    |    |
+----+----+----+----+----+----+
| 2  |    | 1  |    |    |    |
+----+----+----+----+----+----+
| 3  | 3  |    |    |    |    |
+----+----+----+----+----+----+
| 4  |    |    | 4  | 1  | 3  |
+----+----+----+----+----+----+

You can see a live demo on rextester.

答案 1 :(得分:0)

我想出了一个对后一种数据不太好的解决方案,有更好的方法吗?

CREATE TABLE #Split (ID int, String1 varchar(10),  String1Quantity int, String2 varchar(10), String2Quantity int, String3 VARCHAR(10), String3Quantity int, String4 varchar(10), String4Quantity int, String5 varchar(10), String5Quantity int)

Insert into #Split (ID, String1, String1Quantity, String2, String2Quantity, String3, String3Quantity, String4, String4Quantity, String5, String5Quantity) values 
(1,'20',4,'10',1,'20',3, '20', 10, '20', 3),
(2,'20',1,'10',3,null,null, null, null, null, null),
(3,'10',3,'10',3,null,null, null, null, null, null),
(4,'30',4,'40',1,'50',3, '40', 8, '10', 1)

select 
    ID,
    CASE 
        WHEN String1 = '10' and String2 = '10' and String3 = '10' and String4 = '10' and String5 = '10' THEN SUM(String1Quantity+String2Quantity+String3Quantity+String4Quantity+String5Quantity)
        WHEN String1 = '10' and String2 = '10' and String3 = '10' and String4 = '10' THEN SUM(String1Quantity+String2Quantity+String3Quantity+String4Quantity)
        WHEN String1 = '10' and String2 = '10' and String3 = '10' and String5 = '10' THEN SUM(String1Quantity+String2Quantity+String3Quantity+String5Quantity)
        WHEN String1 = '10' and String3 = '10' and String4 = '10' and String5 = '10' THEN SUM(String1Quantity+String3Quantity+String3Quantity+String4Quantity)
        WHEN String2 = '10' and String3 = '10' and String4 = '10' and String5 = '10' THEN SUM(String2Quantity+String3Quantity+String4Quantity+String5Quantity)
        WHEN String1 = '10' and String2 = '10' and String3 = '10' THEN SUM(String1Quantity+String2Quantity+String3Quantity)
        WHEN String1 = '10' and String2 = '10' and String4 = '10' THEN SUM(String1Quantity+String2Quantity+String4Quantity)
        WHEN String1 = '10' and String2 = '10' and String5 = '10' THEN SUM(String1Quantity+String2Quantity+String5Quantity)
        WHEN String1 = '10' and String3 = '10' and String4 = '10' THEN SUM(String1Quantity+String3Quantity+String4Quantity)
        WHEN String1 = '10' and String3 = '10' and String5 = '10' THEN SUM(String1Quantity+String3Quantity+String5Quantity)
        WHEN String1 = '10' and String4 = '10' and String5 = '10' THEN SUM(String1Quantity+String4Quantity+String5Quantity)
        WHEN String2 = '10' and String3 = '10' and String4 = '10' THEN SUM(String2Quantity+String3Quantity+String4Quantity)
        WHEN String2 = '10' and String3 = '10' and String5 = '10' THEN SUM(String2Quantity+String3Quantity+String5Quantity)
        WHEN String2 = '10' and String4 = '10' and String5 = '10' THEN SUM(String2Quantity+String4Quantity+String5Quantity)
        WHEN String3 = '10' and String4 = '10' and String5 = '10' THEN SUM(String3Quantity+String4Quantity+String5Quantity)
        WHEN String3 = '10' and String5 = '10' THEN SUM(String3Quantity+String5Quantity)
        WHEN String3 = '10' and String4 = '10' THEN SUM(String3Quantity+String4Quantity)
        WHEN String2 = '10' and String5 = '10' THEN SUM(String2Quantity+String5Quantity)
        WHEN String2 = '10' and String4 = '10' THEN SUM(String2Quantity+String4Quantity)
        WHEN String2 = '10' and String3 = '10' THEN SUM(String2Quantity+String3Quantity)
        WHEN String1 = '10' and String5 = '10' THEN SUM(String1Quantity+String5Quantity)
        WHEN String1 = '10' and String4 = '10' THEN SUM(String1Quantity+String4Quantity)
        WHEN String1 = '10' and String3 = '10' THEN SUM(String1Quantity+String3Quantity)
        WHEN String1 = '10' and String2 = '10' THEN SUM(String1Quantity+String2Quantity)
        WHEN String5 = '10' THEN SUM(String5Quantity)
        WHEN String4 = '10' THEN SUM(String4Quantity)
        WHEN String3 = '10' THEN SUM(String3Quantity)
        WHEN String2 = '10' THEN SUM(String2Quantity) 
        WHEN String1 = '10' THEN SUM(String1Quantity) 
    END AS '10',

    CASE 
        WHEN String1 = '20' and String2 = '20' and String3 = '20' and String4 = '20' and String5 = '20' THEN SUM(String1Quantity+String2Quantity+String3Quantity+String4Quantity+String5Quantity)
        WHEN String1 = '20' and String2 = '20' and String3 = '20' and String4 = '20' THEN SUM(String1Quantity+String2Quantity+String3Quantity+String4Quantity)
        WHEN String1 = '20' and String2 = '20' and String3 = '20' and String5 = '20' THEN SUM(String1Quantity+String2Quantity+String3Quantity+String5Quantity)
        WHEN String1 = '20' and String3 = '20' and String4 = '20' and String5 = '20' THEN SUM(String1Quantity+String3Quantity+String3Quantity+String4Quantity)
        WHEN String2 = '20' and String3 = '20' and String4 = '20' and String5 = '20' THEN SUM(String2Quantity+String3Quantity+String4Quantity+String5Quantity)
        WHEN String1 = '20' and String2 = '20' and String3 = '20' THEN SUM(String1Quantity+String2Quantity+String3Quantity)
        WHEN String1 = '20' and String2 = '20' and String4 = '20' THEN SUM(String1Quantity+String2Quantity+String4Quantity)
        WHEN String1 = '20' and String2 = '20' and String5 = '20' THEN SUM(String1Quantity+String2Quantity+String5Quantity)
        WHEN String1 = '20' and String3 = '20' and String4 = '20' THEN SUM(String1Quantity+String3Quantity+String4Quantity)
        WHEN String1 = '20' and String3 = '20' and String5 = '20' THEN SUM(String1Quantity+String3Quantity+String5Quantity)
        WHEN String1 = '20' and String4 = '20' and String5 = '20' THEN SUM(String1Quantity+String4Quantity+String5Quantity)
        WHEN String2 = '20' and String3 = '20' and String4 = '20' THEN SUM(String2Quantity+String3Quantity+String4Quantity)
        WHEN String2 = '20' and String3 = '20' and String5 = '20' THEN SUM(String2Quantity+String3Quantity+String5Quantity)
        WHEN String2 = '20' and String4 = '20' and String5 = '20' THEN SUM(String2Quantity+String4Quantity+String5Quantity)
        WHEN String3 = '20' and String4 = '20' and String5 = '20' THEN SUM(String3Quantity+String4Quantity+String5Quantity)
        WHEN String3 = '20' and String5 = '20' THEN SUM(String3Quantity+String5Quantity)
        WHEN String3 = '20' and String4 = '20' THEN SUM(String3Quantity+String4Quantity)
        WHEN String2 = '20' and String5 = '20' THEN SUM(String2Quantity+String5Quantity)
        WHEN String2 = '20' and String4 = '20' THEN SUM(String2Quantity+String4Quantity)
        WHEN String2 = '20' and String3 = '20' THEN SUM(String2Quantity+String3Quantity)
        WHEN String1 = '20' and String5 = '20' THEN SUM(String1Quantity+String5Quantity)
        WHEN String1 = '20' and String4 = '20' THEN SUM(String1Quantity+String4Quantity)
        WHEN String1 = '20' and String3 = '20' THEN SUM(String1Quantity+String3Quantity)
        WHEN String1 = '20' and String2 = '20' THEN SUM(String1Quantity+String2Quantity)
        WHEN String5 = '20' THEN SUM(String5Quantity)
        WHEN String4 = '20' THEN SUM(String4Quantity)
        WHEN String3 = '20' THEN SUM(String3Quantity)
        WHEN String2 = '20' THEN SUM(String2Quantity) 
        WHEN String1 = '20' THEN SUM(String1Quantity) 
    END AS '20',

    CASE 
        WHEN String1 = '30' and String2 = '30' and String3 = '30' and String4 = '30' and String5 = '30' THEN SUM(String1Quantity+String2Quantity+String3Quantity+String4Quantity+String5Quantity)
        WHEN String1 = '30' and String2 = '30' and String3 = '30' and String4 = '30' THEN SUM(String1Quantity+String2Quantity+String3Quantity+String4Quantity)
        WHEN String1 = '30' and String2 = '30' and String3 = '30' and String5 = '30' THEN SUM(String1Quantity+String2Quantity+String3Quantity+String5Quantity)
        WHEN String1 = '30' and String3 = '30' and String4 = '30' and String5 = '30' THEN SUM(String1Quantity+String3Quantity+String3Quantity+String4Quantity)
        WHEN String2 = '30' and String3 = '30' and String4 = '30' and String5 = '30' THEN SUM(String2Quantity+String3Quantity+String4Quantity+String5Quantity)
        WHEN String1 = '30' and String2 = '30' and String3 = '30' THEN SUM(String1Quantity+String2Quantity+String3Quantity)
        WHEN String1 = '30' and String2 = '30' and String4 = '30' THEN SUM(String1Quantity+String2Quantity+String4Quantity)
        WHEN String1 = '30' and String2 = '30' and String5 = '30' THEN SUM(String1Quantity+String2Quantity+String5Quantity)
        WHEN String1 = '30' and String3 = '30' and String4 = '30' THEN SUM(String1Quantity+String3Quantity+String4Quantity)
        WHEN String1 = '30' and String3 = '30' and String5 = '30' THEN SUM(String1Quantity+String3Quantity+String5Quantity)
        WHEN String1 = '30' and String4 = '30' and String5 = '30' THEN SUM(String1Quantity+String4Quantity+String5Quantity)
        WHEN String2 = '30' and String3 = '30' and String4 = '30' THEN SUM(String2Quantity+String3Quantity+String4Quantity)
        WHEN String2 = '30' and String3 = '30' and String5 = '30' THEN SUM(String2Quantity+String3Quantity+String5Quantity)
        WHEN String2 = '30' and String4 = '30' and String5 = '30' THEN SUM(String2Quantity+String4Quantity+String5Quantity)
        WHEN String3 = '30' and String4 = '30' and String5 = '30' THEN SUM(String3Quantity+String4Quantity+String5Quantity)
        WHEN String3 = '30' and String5 = '30' THEN SUM(String3Quantity+String5Quantity)
        WHEN String3 = '30' and String4 = '30' THEN SUM(String3Quantity+String4Quantity)
        WHEN String2 = '30' and String5 = '30' THEN SUM(String2Quantity+String5Quantity)
        WHEN String2 = '30' and String4 = '30' THEN SUM(String2Quantity+String4Quantity)
        WHEN String2 = '30' and String3 = '30' THEN SUM(String2Quantity+String3Quantity)
        WHEN String1 = '30' and String5 = '30' THEN SUM(String1Quantity+String5Quantity)
        WHEN String1 = '30' and String4 = '30' THEN SUM(String1Quantity+String4Quantity)
        WHEN String1 = '30' and String3 = '30' THEN SUM(String1Quantity+String3Quantity)
        WHEN String1 = '30' and String2 = '30' THEN SUM(String1Quantity+String2Quantity)
        WHEN String5 = '30' THEN SUM(String5Quantity)
        WHEN String4 = '30' THEN SUM(String4Quantity)
        WHEN String3 = '30' THEN SUM(String3Quantity)
        WHEN String2 = '30' THEN SUM(String2Quantity) 
        WHEN String1 = '30' THEN SUM(String1Quantity) 
    END AS '30',

    CASE 
        WHEN String1 = '40' and String2 = '40' and String3 = '40' and String4 = '40' and String5 = '40' THEN SUM(String1Quantity+String2Quantity+String3Quantity+String4Quantity+String5Quantity)
        WHEN String1 = '40' and String2 = '40' and String3 = '40' and String4 = '40' THEN SUM(String1Quantity+String2Quantity+String3Quantity+String4Quantity)
        WHEN String1 = '40' and String2 = '40' and String3 = '40' and String5 = '40' THEN SUM(String1Quantity+String2Quantity+String3Quantity+String5Quantity)
        WHEN String1 = '40' and String3 = '40' and String4 = '40' and String5 = '40' THEN SUM(String1Quantity+String3Quantity+String3Quantity+String4Quantity)
        WHEN String2 = '40' and String3 = '40' and String4 = '40' and String5 = '40' THEN SUM(String2Quantity+String3Quantity+String4Quantity+String5Quantity)
        WHEN String1 = '40' and String2 = '40' and String3 = '40' THEN SUM(String1Quantity+String2Quantity+String3Quantity)
        WHEN String1 = '40' and String2 = '40' and String4 = '40' THEN SUM(String1Quantity+String2Quantity+String4Quantity)
        WHEN String1 = '40' and String2 = '40' and String5 = '40' THEN SUM(String1Quantity+String2Quantity+String5Quantity)
        WHEN String1 = '40' and String3 = '40' and String4 = '40' THEN SUM(String1Quantity+String3Quantity+String4Quantity)
        WHEN String1 = '40' and String3 = '40' and String5 = '40' THEN SUM(String1Quantity+String3Quantity+String5Quantity)
        WHEN String1 = '40' and String4 = '40' and String5 = '40' THEN SUM(String1Quantity+String4Quantity+String5Quantity)
        WHEN String2 = '40' and String3 = '40' and String4 = '40' THEN SUM(String2Quantity+String3Quantity+String4Quantity)
        WHEN String2 = '40' and String3 = '40' and String5 = '40' THEN SUM(String2Quantity+String3Quantity+String5Quantity)
        WHEN String2 = '40' and String4 = '40' and String5 = '40' THEN SUM(String2Quantity+String4Quantity+String5Quantity)
        WHEN String3 = '40' and String4 = '40' and String5 = '40' THEN SUM(String3Quantity+String4Quantity+String5Quantity)
        WHEN String3 = '40' and String5 = '40' THEN SUM(String3Quantity+String5Quantity)
        WHEN String3 = '40' and String4 = '40' THEN SUM(String3Quantity+String4Quantity)
        WHEN String2 = '40' and String5 = '40' THEN SUM(String2Quantity+String5Quantity)
        WHEN String2 = '40' and String4 = '40' THEN SUM(String2Quantity+String4Quantity)
        WHEN String2 = '40' and String3 = '40' THEN SUM(String2Quantity+String3Quantity)
        WHEN String1 = '40' and String5 = '40' THEN SUM(String1Quantity+String5Quantity)
        WHEN String1 = '40' and String4 = '40' THEN SUM(String1Quantity+String4Quantity)
        WHEN String1 = '40' and String3 = '40' THEN SUM(String1Quantity+String3Quantity)
        WHEN String1 = '40' and String2 = '40' THEN SUM(String1Quantity+String2Quantity)
        WHEN String5 = '40' THEN SUM(String5Quantity)
        WHEN String4 = '40' THEN SUM(String4Quantity)
        WHEN String3 = '40' THEN SUM(String3Quantity)
        WHEN String2 = '40' THEN SUM(String2Quantity) 
        WHEN String1 = '40' THEN SUM(String1Quantity) 
    END AS '40',

    CASE 
        WHEN String1 = '50' and String2 = '50' and String3 = '50' and String4 = '50' and String5 = '50' THEN SUM(String1Quantity+String2Quantity+String3Quantity+String4Quantity+String5Quantity)
        WHEN String1 = '50' and String2 = '50' and String3 = '50' and String4 = '50' THEN SUM(String1Quantity+String2Quantity+String3Quantity+String4Quantity)
        WHEN String1 = '50' and String2 = '50' and String3 = '50' and String5 = '50' THEN SUM(String1Quantity+String2Quantity+String3Quantity+String5Quantity)
        WHEN String1 = '50' and String3 = '50' and String4 = '50' and String5 = '50' THEN SUM(String1Quantity+String3Quantity+String3Quantity+String4Quantity)
        WHEN String2 = '50' and String3 = '50' and String4 = '50' and String5 = '50' THEN SUM(String2Quantity+String3Quantity+String4Quantity+String5Quantity)
        WHEN String1 = '50' and String2 = '50' and String3 = '50' THEN SUM(String1Quantity+String2Quantity+String3Quantity)
        WHEN String1 = '50' and String2 = '50' and String4 = '50' THEN SUM(String1Quantity+String2Quantity+String4Quantity)
        WHEN String1 = '50' and String2 = '50' and String5 = '50' THEN SUM(String1Quantity+String2Quantity+String5Quantity)
        WHEN String1 = '50' and String3 = '50' and String4 = '50' THEN SUM(String1Quantity+String3Quantity+String4Quantity)
        WHEN String1 = '50' and String3 = '50' and String5 = '50' THEN SUM(String1Quantity+String3Quantity+String5Quantity)
        WHEN String1 = '50' and String4 = '50' and String5 = '50' THEN SUM(String1Quantity+String4Quantity+String5Quantity)
        WHEN String2 = '50' and String3 = '50' and String4 = '50' THEN SUM(String2Quantity+String3Quantity+String4Quantity)
        WHEN String2 = '50' and String3 = '50' and String5 = '50' THEN SUM(String2Quantity+String3Quantity+String5Quantity)
        WHEN String2 = '50' and String4 = '50' and String5 = '50' THEN SUM(String2Quantity+String4Quantity+String5Quantity)
        WHEN String3 = '50' and String4 = '50' and String5 = '50' THEN SUM(String3Quantity+String4Quantity+String5Quantity)
        WHEN String3 = '50' and String5 = '50' THEN SUM(String3Quantity+String5Quantity)
        WHEN String3 = '50' and String4 = '50' THEN SUM(String3Quantity+String4Quantity)
        WHEN String2 = '50' and String5 = '50' THEN SUM(String2Quantity+String5Quantity)
        WHEN String2 = '50' and String4 = '50' THEN SUM(String2Quantity+String4Quantity)
        WHEN String2 = '50' and String3 = '50' THEN SUM(String2Quantity+String3Quantity)
        WHEN String1 = '50' and String5 = '50' THEN SUM(String1Quantity+String5Quantity)
        WHEN String1 = '50' and String4 = '50' THEN SUM(String1Quantity+String4Quantity)
        WHEN String1 = '50' and String3 = '50' THEN SUM(String1Quantity+String3Quantity)
        WHEN String1 = '50' and String2 = '50' THEN SUM(String1Quantity+String2Quantity)
        WHEN String5 = '50' THEN SUM(String5Quantity)
        WHEN String4 = '50' THEN SUM(String4Quantity)
        WHEN String3 = '50' THEN SUM(String3Quantity)
        WHEN String2 = '50' THEN SUM(String2Quantity) 
        WHEN String1 = '50' THEN SUM(String1Quantity) 
    END AS '50'

From #Split
Group by Id, String1, String2, String3, string4, String5

drop table #Split