簡體   English   中英

SQL SELECT 以逗號分隔值連接不同的列值

[英]SQL SELECT concatenate distinct column values in comma separated value

我有一個包含訂單詳細信息的表。 該表的每一行都是訂單的一個項目,每一行都有一個名為服務的列,這是一個以逗號分隔的與該項目相關的服務列表。

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 版權所有 (c) 1988-2005 Microsoft Corporation Enterprise Edition(64 位)Windows NT 6.1(Build 7601:Service Pack 1)

數據庫小提琴

或 SQL 代碼復制示例

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

您可以在 SQL Server 2005 中使用拆分 function 執行此操作,例如來自 這篇文章

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;

Output:

order_id 訂單_服務
1個 123,456
2個 123,456,789

如果您認為,“哇,這真是一個丑陋而復雜的查詢。” 沒錯,SQL 服務器的現代版本支持更優雅的方法,並且正確規范化的數據首先不需要任何版本的任何此類雜技。

SQL Server 2017+ 中的方法不需要自定義 function 或混亂的 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;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM