วิธีใช้ COALESCE กับหลายแถวและไม่มีเครื่องหมายจุลภาคก่อนหน้า


27

ฉันกำลังพยายามทำสิ่งต่อไปนี้:

California | Los Angeles, San Francisco, Sacramento
Florida    | Jacksonville, Miami

น่าเสียดายที่ฉันได้รับ ", Los Angeles, San Francisco, Sacramento, Jacksonville, Miami"

ฉันสามารถบรรลุผลลัพธ์ที่ต้องการโดยใช้ฟังก์ชั่น STUFF แต่สงสัยว่ามีวิธีที่สะอาดกว่าในการทำโดยใช้ COALESCE หรือไม่

STATE       | CITY
California  | San Francisco
California  | Los Angeles
California  | Sacramento
Florida     | Miami
Florida     | Jacksonville 


DECLARE @col NVARCHAR(MAX);
SELECT @col= COALESCE(@col, '') + ',' + city
FROM tbl where city = 'California';
SELECT @col;

ขอบคุณ

คำตอบ:


45

นี่อาจเป็นวิธีที่สะอาดกว่าที่คุณต้องการ ตรวจสอบว่าตัวแปรนั้นได้รับการเริ่มต้นหรือยัง หากไม่มีให้ตั้งเป็นสตริงว่างและต่อท้ายเมืองแรก (ไม่มีเครื่องหมายจุลภาคชั้นนำ) ถ้ามีให้ต่อท้ายคอมมาแล้วต่อท้ายเมือง

DECLARE @col nvarchar(MAX);
SELECT @col = COALESCE(@col + ',', '') + city
  FROM dbo.tbl WHERE state = 'California';

แน่นอนว่าใช้ได้กับการเติมตัวแปรต่อสถานะเท่านั้น หากคุณกำลังดึงรายการสำหรับแต่ละรัฐทีละรายการมีทางออกที่ดีกว่าในนัดเดียว:

SELECT [state], cities = STUFF((
    SELECT N', ' + city FROM dbo.tbl
    WHERE [state] = x.[state]
    FOR XML PATH(''), TYPE).value(N'.[1]', N'nvarchar(max)'), 1, 2, N'')
FROM dbo.tbl AS x
GROUP BY [state]
ORDER BY [state];

ผล:

state       cities
----------  --------------------------------------
California  San Francisco, Los Angeles, Sacramento  
Florida     Miami, Jacksonville

หากต้องการจัดเรียงตามชื่อเมืองภายในแต่ละรัฐ:

SELECT [state], cities = STUFF((
    SELECT N', ' + city FROM dbo.tbl
    WHERE [state] = x.[state]
    ORDER BY city
    FOR XML PATH(''), TYPE).value(N'.[1]', N'nvarchar(max)'), 1, 2, N'')
FROM dbo.tbl AS x
GROUP BY [state]
ORDER BY [state];

ใน Azure SQL Database หรือ SQL Server 2017+ คุณสามารถใช้ฟังก์ชันใหม่STRING_AGG() :

SELECT [state], cities = STRING_AGG(city, N', ')
  FROM dbo.tbl
  GROUP BY [state]
  ORDER BY [state];

และเรียงตามชื่อเมือง:

SELECT [state], cities = STRING_AGG(city, N', ') 
                         WITHIN GROUP (ORDER BY city)
  FROM dbo.tbl
  GROUP BY [state]
  ORDER BY [state];

ขอบคุณแอรอน โซลูชันปัจจุบันของฉันใกล้เคียงกับคุณยกเว้นว่าฉันใช้ DISTINCT แทนที่จะเป็น GROUP BY
2732180

2
@ user2732180 คุณควรใช้ GROUP BY เนื่องจากมีแนวโน้มที่จะทำการต่อข้อมูลหนึ่งครั้งต่อรัฐ ด้วย DISTINCT มันจะใช้การเรียงต่อกันที่เหมือนกันสำหรับทุก ๆ ตัวอย่างของแคลิฟอร์เนียและจากนั้นทิ้งงานทั้งหมดที่ทำให้เกิดการซ้ำซ้อนเหล่านั้น
แอรอนเบอร์ทรานด์ด์

6

เพียงเพิ่มคำตอบของแอรอนด้านบน ...

โปรดทราบว่าตัวORDER BYแบ่งอาจรวมเฉพาะรายการสุดท้ายในแบบสอบถามของคุณ ในกรณีของฉันฉันไม่ได้จัดกลุ่มดังนั้นไม่แน่ใจว่าจะสร้างความแตกต่างได้ไหม ฉันใช้ SQL 2014 ในกรณีของฉันฉันมีบางอย่างเช่น value1, value2, value3 ... แต่ผลลัพธ์ของฉันในตัวแปรคือ value3 เท่านั้น


แอรอนแสดงความคิดเห็นว่า:

มีการรายงานอย่างน้อยสี่ครั้งในการเชื่อมต่อ:

  1. ในการเรียงต่อกันตัวแปรและการสั่งซื้อโดยผลการกรอง (เช่นที่เงื่อนไข)
  2. (n) การสร้าง varchar จาก ResultSet ล้มเหลวเมื่อเพิ่ม ORDER BY
  3. การกำหนดตัวแปรโลคัลจาก SELECT ที่สั่งซื้อพร้อมกับ CROSS APPLYs และฟังก์ชั่นที่มีค่าเป็นตารางจะคืนค่าสุดท้ายเท่านั้น
  4. เมื่อทำการเชื่อมต่อค่า varchar (สูงสุด) / nvarchar (สูงสุด) จากตัวแปรตารางผลลัพธ์ที่ไม่ถูกต้องอาจถูกส่งคืนหากการกรองและการสั่งซื้อโดยคอลัมน์ที่ไม่ใช่คีย์หลัก

ตัวอย่างคำตอบจาก Microsoft:

พฤติกรรมที่คุณเห็นคือจากการออกแบบ การใช้การดำเนินการที่ได้รับมอบหมาย (การต่อข้อมูลในตัวอย่างนี้) ในแบบสอบถามที่มีคำสั่ง ORDER BY มีพฤติกรรมที่ไม่ได้กำหนด

การตอบกลับยังอ้างอิง KB 287515:

PRB: แผนการดำเนินการและผลลัพธ์ของแบบสอบถามการต่อข้อมูลรวมขึ้นอยู่กับตำแหน่งที่ตั้งของนิพจน์

การแก้ปัญหาคือการใช้ FOR XML PATH (วิธีที่สองในคำตอบของแอรอน) หากคำสั่งของการเรียงต่อกันมีความสำคัญและแน่นอนถ้าคุณต้องการให้แน่ใจว่าจะรวมค่าทั้งหมด ดูเพิ่มเติมที่:

การเชื่อมต่อ nvarchar / index / nvarchar (สูงสุด) พฤติกรรมที่อธิบายไม่ได้บน Stack Overflow

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.