本文介紹了根據(jù)位置和分隔符拆分字符串的處理方法,對大家解決問題具有一定的參考價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧!
問題描述
我需要幫助。
關(guān)于CHARINDEX、PATINDEX、SUBSTRING、LEFT和RIGHT上的SQL的問題。
我有需要根據(jù)位置和分隔符拆分的字符串。其中一部分用作列名,另一部分用作數(shù)據(jù)。并基于行ID對其進(jìn)行分組。然后根據(jù)需要對這些值求和。
樣本數(shù)據(jù)、ID、字符串
1 20:4:10:1:20:3:
2 20:1:
3 10:3:
4 30:4:40:1:50:3:
并且所需的結(jié)果是
id 10 20 30 40 50
1 1 7
2 1
3 3
4 4 1 3
數(shù)據(jù):
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
如有任何幫助,不勝感激!
數(shù)據(jù)也可能是這樣的:
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
推薦答案
首先,正如我在評論中所寫的:解決此問題的解決方案是修復(fù)損壞的數(shù)據(jù)模型。有關(guān)更多信息,請閱讀Is storing a delimited list in a database column really that bad?,在那里您將看到此問題的答案絕對是的許多原因!
話雖如此,我知道很多時(shí)候,出于許多不同的原因,更改數(shù)據(jù)庫結(jié)構(gòu)不是一種選擇,即使這會(huì)解決許多問題。
現(xiàn)在,根據(jù)您的字符串操作函數(shù),我假設(shè)您正在使用SQL-Server(請注意,對于每個(gè)SQL問題,您應(yīng)該始終指定RDBMS和版本,或者如果您確實(shí)需要跨數(shù)據(jù)庫解決方案,請使用database-agnostic)。
因此,根據(jù)您的假設(shè),您最好的選擇可能是使用Jeff Moden’s DelimitedSplit8KUDF將字符串拆分成表。
此函數(shù)將返回一個(gè)包含兩列的表-一列用于子字符串,另一列用于源字符串中的索引-這正是您開始構(gòu)建所需結(jié)果所需的。
因此,基于該函數(shù)、幾個(gè)公用表表達(dá)式、透視和條件聚合,我得出了以下解決方案:
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;
結(jié)果:
+----+----+----+----+----+----+
| 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.
這篇關(guān)于根據(jù)位置和分隔符拆分字符串的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,