本文介紹了根據位置和分隔符拆分字符串的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!
問題描述
我需要幫助。
關于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
推薦答案
首先,正如我在評論中所寫的:解決此問題的解決方案是修復損壞的數據模型。有關更多信息,請閱讀Is storing a delimited list in a database column really that bad?,在那里您將看到此問題的答案絕對是的許多原因!
話雖如此,我知道很多時候,出于許多不同的原因,更改數據庫結構不是一種選擇,即使這會解決許多問題。
現在,根據您的字符串操作函數,我假設您正在使用SQL-Server(請注意,對于每個SQL問題,您應該始終指定RDBMS和版本,或者如果您確實需要跨數據庫解決方案,請使用database-agnostic)。
因此,根據您的假設,您最好的選擇可能是使用Jeff Moden’s DelimitedSplit8KUDF將字符串拆分成表。
此函數將返回一個包含兩列的表-一列用于子字符串,另一列用于源字符串中的索引-這正是您開始構建所需結果所需的。
因此,基于該函數、幾個公用表表達式、透視和條件聚合,我得出了以下解決方案:
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.
這篇關于根據位置和分隔符拆分字符串的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,