假設我們有如下表:如何在一列分割字符串值,並返回結果表
id name member
1 jacky a;b;c
2 jason e
3 kate i;j;k
4 alex null
現在我想用SQL或T-SQL來如下表返回:
1 jacky a
1 jacky b
1 jacky c
2 jason e
3 kate i
......
如何做到這一點? 我正在使用MSSQL,MYSQL和Oracle數據庫。
假設我們有如下表:如何在一列分割字符串值,並返回結果表
id name member
1 jacky a;b;c
2 jason e
3 kate i;j;k
4 alex null
現在我想用SQL或T-SQL來如下表返回:
1 jacky a
1 jacky b
1 jacky c
2 jason e
3 kate i
......
如何做到這一點? 我正在使用MSSQL,MYSQL和Oracle數據庫。
這是最短和可讀字符串到行分離器一個可以設計,並且可能是更快了。
選擇純CTE而不是功能的使用案例,例如當您不允許在數據庫上創建函數時:-)
通過函數創建行生成器(可以通過循環或通過CTE實現)仍然需要使用橫向連接(DB2和Sybase擁有此功能功能,使用LATERAL關鍵字;在SQL Server中,這與CROSS APPLY和OUTER APPLY類似)最終將由函數生成的拆分行連接到主表。
純粹的CTE方法可能比函數方法更快。速度指標在於分析,雖然,只是檢查的這相對於其他解決方案的執行計劃,如果這確實是快:
with Pieces(theId, pn, start, stop) AS
(
SELECT id, 1, 1, charindex(';', member)
from tbl
UNION ALL
SELECT id, pn + 1, stop + 1, charindex(';', member, stop + 1)
from tbl
join pieces on pieces.theId = tbl.id
WHERE stop > 0
)
select
t.id, t.name,
word =
substring(t.member, p.start,
case WHEN stop > 0 THEN p.stop - p.start
ELSE 512
END)
from tbl t
join pieces p on p.theId = t.id
order by t.id, p.pn
輸出:
ID NAME WORD
1 jacky a
1 jacky b
1 jacky c
2 jason e
3 kate i
3 kate j
3 kate k
4 alex (null)
基本邏輯這裏來源:T-SQL: Opposite to string concatenation - how to split string into multiple records
那麼......讓我先向你介紹一下Adam Machanic,他教會了我一個Numbers表。他還使用這個Numbers表格編寫了一個非常快速的分割函數。
您實現返回一個表拆分功能後,您就可以加入反對它,並得到你想要的結果。
我瞭解dbo.SplitString('東西,別的東西等等等等等等',',')函數。但是如何用這個函數得到結果表。 – DerekY
@ user838204如果您使用了某個功能,則應使用CROSS APPLY或OUTER APPLY。這種格式:'SELECT * FROM tbl OUTER APPLY(select * FROM dbo.splitter(tbl.member))' –
IF OBJECT_ID('dbo.Users') IS NOT NULL
DROP TABLE dbo.Users;
CREATE TABLE dbo.Users
(
id INT IDENTITY NOT NULL PRIMARY KEY,
name VARCHAR(50) NOT NULL,
member VARCHAR(1000)
)
GO
INSERT INTO dbo.Users(name, member) VALUES
('jacky', 'a;b;c'),
('jason', 'e'),
('kate', 'i;j;k'),
('alex', NULL);
GO
DECLARE @spliter CHAR(1) = ';';
WITH Base AS
(
SELECT 1 AS n
UNION ALL
SELECT n + 1
FROM Base
WHERE n < CEILING(SQRT(1000)) --generate numbers from 1 to 1000, you may change it to a larger value depending on the member column's length.
)
, Nums AS --Numbers Common Table Expression, if your database version doesn't support it, just create a physical table.
(
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT 0)) AS n
FROM Base AS B1 CROSS JOIN Base AS B2
)
SELECT id,
SUBSTRING(member, n, CHARINDEX(@spliter, member + @spliter, n) - n) AS element
FROM dbo.Users
JOIN Nums
ON n <= DATALENGTH(member) + 1
AND SUBSTRING(@spliter + member, n, 1) = @spliter
ORDER BY id
OPTION (MAXRECURSION 0); --Nums CTE is generated recursively, we don't want to limit recursion count.
Unpivot是你在MSSQL和oracle尋找的命令 – xQbert
@xQbert - 我不認爲unpivot具有拆分功能,但我可能是錯的... –