Разделить строку на основе позиции и разделителей - PullRequest
0 голосов
/ 06 февраля 2020

Мне нужна помощь. Вопрос о SQL для CHARINDEX, PATINDEX, SUBSTRING, LEFT и RIGHT.

У меня есть строки, которые мне нужно разделить в зависимости от положения и разделителя. Используя некоторые из них в качестве имени столбца, а другую часть в качестве данных. и сгруппировать это на основе идентификатора строки. И затем суммируйте значения, если необходимо.

Пример данных, 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 ]

1 голос
/ 06 февраля 2020

Во-первых, как я написал в своем комментарии: решение для этого состоит в том, чтобы исправить вашу поврежденную модель данных. Для получения дополнительной информации читайте Действительно ли плохо хранить список с разделителями в столбце базы данных? , где вы увидите множество причин, по которым ответ на этот вопрос Абсолютно да!

С учетом сказанного я знаю, что во многих случаях по разным причинам изменение структуры базы данных невозможно, даже если это решит множество проблем.

Теперь, основываясь на ваших функциях работы со строками, я предполагаю, что вы работаете с SQL -Server (Обратите внимание, что для каждого sql вопроса вы всегда должны указывать rdbms и версию или использовать , если вам действительно необходимо решение для работы с несколькими базами данных).

Поэтому, исходя из ваших предположений, вам лучше всего использовать 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  |
+----+----+----+----+----+----+

Вы можете увидеть живое демо на rextester.

0 голосов
/ 06 февраля 2020

Я нашел не слишком элегантное решение для последних данных, есть ли лучший способ сделать это?

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
...