我有一個包含訂單詳細資訊的表格。該表的每一行都是訂單的一個專案,每一行都有一個名為 services 的列,這是一個逗號分隔的與該專案相關的服務串列。
| ID | order_id | 服務 |
|---|---|---|
| 1 | 1 | 123 |
| 2 | 1 | 123,456 |
| 3 | 2 | 456,789 |
| 4 | 2 | 123 |
| 5 | 2 | 789,456 |
我達到的是連續的結果
| 訂單服務 |
|---|
| 123,123,456 |
使用此查詢獲得
SELECT STUFF(
(SELECT DISTINCT ',' services
FROM order_detail
WHERE order_id = 1
FOR XML PATH ('')), 1, 1, '') AS Order_Services
我想從單個 order_id 中獲得一個串聯服務的結果集,但我也想洗掉重復項。STUFF 中的 distinc 非常沒用,因為它只洗掉相等的列(例如,不洗掉值 '123,456' 和 '456,123' 之一,因為不是同一件事)
我的預期結果是,
對于order_id=1
| 訂單服務 |
|---|
| 123,456 |
對于order_id=2
| 訂單服務 |
|---|
| 123,456,789 |
有沒有一種簡單的方法可以實作這一目標?
我的 SQL 版本是:
Microsoft SQL Server 2005 - 9.00.4035.00 (X64) Nov 24 2008 16:17:31 Copyright (c) 1988-2005 Microsoft Corporation Enterprise Edition (64-bit) on Windows NT 6.1 (Build 7601: Service Pack 1)
DBFiddle
or SQL code for replicate the example
CREATE TABLE order_detail ( ID INT IDENTITY(1,1) PRIMARY KEY, order_id INT, services varchar(100));
INSERT INTO order_detail (order_id,services) VALUES (1, '123' ), (1, '123,456' ), (2, '456,789' ),(2,'123'),(2,'789,456')
SELECT
STUFF(
(SELECT DISTINCT ',' services
FROM order_detail
WHERE order_id = 1
FOR XML PATH (''))
, 1, 1, '') AS Order_Services
uj5u.com熱心網友回復:
您可以在 SQL Server 2005 中使用拆分功能執行此操作,例如來自這篇文章:
CREATE FUNCTION dbo.SplitStrings_XML
(
@List nvarchar(max),
@Delimiter nvarchar(255)
)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN
(
SELECT Item = y.i.value(N'(./text())[1]', N'nvarchar(4000)')
FROM
(
SELECT x = CONVERT(XML, '<i>'
REPLACE(@List, @Delimiter, '</i><i>')
'</i>').query('.')
) AS a CROSS APPLY x.nodes('i') AS y(i)
);
GO
然后你可以說:
;WITH cte AS
(
SELECT d.order_id, f.Item
FROM dbo.order_detail AS d
CROSS APPLY dbo.SplitStrings_XML(d.services, ',') AS f
GROUP BY d.order_id, f.Item
),
sub AS
(
SELECT cte.order_id, Order_Services = STUFF(
(SELECT ',' x.Item
FROM cte AS x
WHERE x.order_id = cte.order_id
FOR XML PATH(''),
TYPE).value(N'./text()[1]', N'varchar(max)'),
1, 1, '')
FROM cte
)
SELECT order_id, Order_Services
FROM sub
GROUP BY order_id, Order_Services;
輸出:
| order_id | 訂單服務 |
|---|---|
| 1 | 123,456 |
| 2 | 123,456,789 |
如果你想,“哇,這真是一個丑陋而復雜的查詢!” 你說得對。現代版本的 SQL Server 支持更優雅的方法,并且正確規范化的資料首先不需要任何版本中的任何此類雜技。
SQL Server 2017 中的方法在任一方向都不需要自定義函式或凌亂的 XML 處理:
;WITH cte AS
(
SELECT d.order_id, s.value
FROM dbo.order_detail AS d
CROSS APPLY STRING_SPLIT(d.services, ',') AS s
GROUP BY d.order_id, s.value
)
SELECT order_id, STRING_AGG(value, ',')
FROM cte
GROUP BY order_id;
- 示例db<>fiddle
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/456554.html
標籤:sql sql-server
上一篇:我想在SQLServer中用id和value分隔如下字串
下一篇:使用條件將資料插入表中
