ฟังก์ชัน COALESCE ใน TSQL


คำตอบ:


74

ฉันได้รับแจ้งว่า COALESCE มีค่าใช้จ่ายน้อยกว่า ISNULL แต่การวิจัยไม่ได้ระบุว่า ISNULL ใช้เวลาเพียงสองพารามิเตอร์คือฟิลด์ที่ถูกประเมินเป็นค่า NULL และผลลัพธ์ที่คุณต้องการหากถูกประเมินเป็น NULL COALESCE จะรับพารามิเตอร์จำนวนเท่าใดก็ได้และส่งกลับค่าแรกที่พบซึ่งไม่ใช่ค่า NULL

มีคำอธิบายอย่างละเอียดมากขึ้นเกี่ยวกับรายละเอียดที่นี่ http://www.mssqltips.com/sqlservertip/2689/deciding-between-coalesce-and-isnull-in-sql-server/


6
ระวังการใช้ISNULLมันไม่ได้มาตรฐานมีความยืดหยุ่นน้อยกว่าฉันอ่านว่ามันจะส่งคืนประเภทข้อมูลของอาร์กิวเมนต์แรกเสมอไม่ใช่ประเภทข้อมูลของค่าที่ส่งคืนเช่นCOALESCEdo
sprocket12

215

ฉันไม่แน่ใจว่าทำไมคุณถึงคิดว่าเอกสารนี้คลุมเครือ

NOT NULLมันก็ผ่านไปทุกพารามิเตอร์หนึ่งโดยหนึ่งและส่งกลับคนแรกที่เป็น

COALESCE(NULL, NULL, NULL, 1, 2, 3)
=> 1


COALESCE(1, 2, 3, 4, 5, NULL)
=> 1


COALESCE(NULL, NULL, NULL, 3, 2, NULL)
=> 3


COALESCE(6, 5, 4, 3, 2, NULL)
=> 6


COALESCE(NULL, NULL, NULL, NULL, NULL, NULL)
=> NULL

ยอมรับพารามิเตอร์จำนวนเท่าใดก็ได้ แต่ควรเป็นชนิดข้อมูลเดียวกัน (หากไม่ใช่ประเภทข้อมูลเดียวกันก็จะถูกส่งไปยังประเภทข้อมูลที่เหมาะสมโดยปริยายโดยใช้ลำดับความสำคัญของประเภทข้อมูล )

มันเหมือนกับISNULL()แต่สำหรับพารามิเตอร์หลายตัวแทนที่จะเป็นเพียงสองตัว

นอกจากนี้ยังเป็นANSI-SQLที่-เป็นISNULL()ไม่ได้


4
+1 สำหรับคำอธิบายของคุณเกี่ยวกับลำดับความสำคัญของประเภทข้อมูล ฉันเชื่อว่าISNULLจะส่งคืนค่าที่มีประเภทข้อมูลเดียวกันกับพารามิเตอร์แรกแม้ว่า
Lamak

5
ตัวอย่างโค้ดสุดท้ายของคุณควรให้ข้อผิดพลาด 'อาร์กิวเมนต์อย่างน้อยหนึ่งข้อใน COALESCE ต้องเป็นค่า NULL' ที่มา: sql-server-performance.com/2007/…
maqk

2
เอกสารนี้กล่าวได้มากในขณะเดียวกันก็จัดการให้ค่าเกือบเป็นศูนย์ เอกสารที่ดีให้ตัวอย่างง่ายๆพร้อมผลลัพธ์ง่ายๆ Coalesce ย้ายเข้าทันทีexpressionsเปรียบเทียบกับ CASE เปรียบเทียบกับ ISNULL และในที่สุดก็เป็นตัวอย่างที่ไม่มีผลลัพธ์ จากนั้นเป็นตัวอย่างที่ซับซ้อนเกินไปและมีรายละเอียดมากเกินไป เมื่อสิ่งที่เราต้องการคือคำตอบนี้ด้วย WTF 5-6 บรรทัดสิ่งนี้คือและทำ
พีไบรอันแมคกี้

1
รายละเอียดลำดับความสำคัญ
IsmailS

18

นี่คือวิธีที่ฉันมองไปที่ COALESCE ... และหวังว่ามันจะสมเหตุสมผล ...

ในรูปแบบที่เรียบง่าย….

Coalesce (ชื่อฟิลด์ 'ว่างเปล่า')

ดังนั้นจึงแปลเป็น ... ถ้า "FieldName" เป็น NULL ให้เติมค่าฟิลด์ด้วยคำว่า "EMPTY"

ตอนนี้สำหรับค่าหลายประการ ...

Coalesce (FieldName1, FieldName2, Value2, Value3)

ถ้าค่าใน Fieldname1 เป็นค่าว่างให้เติมด้วยค่าใน Fieldname2 ถ้า FieldName2 เป็น NULL ให้เติมด้วย Value2 เป็นต้น

โค้ดทดสอบชิ้นนี้สำหรับฐานข้อมูลตัวอย่างAdventureWorks2012ทำงานได้อย่างสมบูรณ์และให้คำอธิบายภาพที่ดีว่าCOALESCEทำงานอย่างไร:

SELECT Name, Class, Color, ProductNumber,
COALESCE(Class, Color, ProductNumber) AS FirstNotNull
FROM Production.Product

4

มีอะไรอีกมากมายที่จะรวมตัวกันได้มากกว่าการเปลี่ยน ISNULL ฉันยอมรับอย่างสมบูรณ์ว่า "เอกสาร" อย่างเป็นทางการของการรวมตัวกันนั้นคลุมเครือและไม่เป็นประโยชน์ บทความนี้ช่วยได้มาก http://www.mssqltips.com/sqlservertip/1521/the-many-uses-of-coalesce-in-sql-server/


3
บทความที่คุณเชื่อมโยงนั้นทำให้เข้าใจผิดอย่างมาก (ตามที่หลายคนชี้ให้เห็นรวมถึงผู้เขียนในส่วนความคิดเห็น) เทคนิคที่เป็นระเบียบทั้งหมดที่เขาไฮไลต์สามารถทำได้ทั้งหมดโดยใช้ ISNULL แทนการรวมตัวกัน
Hobo Spider

3

นี่คือแบบสอบถามง่ายๆที่มีการรวมกัน -

select * from person where coalesce(addressId, ContactId) is null.

มันจะส่งคืนบุคคลที่ทั้ง addressId และ contactId เป็นโมฆะ

ฟังก์ชันรวมตัวกัน

  • ใช้เวลาอย่างน้อยสองอาร์กิวเมนต์
  • อาร์กิวเมนต์ต้องเป็นประเภทจำนวนเต็ม
  • ส่งคืนอาร์กิวเมนต์แรกที่ไม่ใช่ค่าว่าง

เช่น

  • การรวมกัน (null, 1, 2, 3) จะส่งคืน 1
  • coalesce (null, null) จะคืนค่า null

1

คำจำกัดความที่ง่ายที่สุดของฟังก์ชัน Coalesce ()อาจเป็น:

ฟังก์ชัน Coalesce () จะประเมินอาร์กิวเมนต์ที่ส่งผ่านทั้งหมดจากนั้นส่งกลับค่าของอินสแตนซ์แรกของอาร์กิวเมนต์ที่ไม่ได้ประเมินเป็นค่า NULL

หมายเหตุ: จะประเมินพารามิเตอร์ทั้งหมดกล่าวคือไม่ข้ามการประเมินอาร์กิวเมนต์ทางด้านขวาของพารามิเตอร์ส่งคืน / ไม่เป็นโมฆะ

ไวยากรณ์:

Coalesce(arg1, arg2, argN...)

ข้อควรระวัง : นอกเหนือจากอาร์กิวเมนต์ที่ประเมินค่าเป็น NULL แล้วอาร์กิวเมนต์อื่น ๆ ทั้งหมด (NOT-NULL) ต้องเป็นประเภทข้อมูลเดียวกันหรือต้องเป็นประเภทการจับคู่ (ซึ่งสามารถ "แปลงอัตโนมัติโดยปริยาย" เป็นประเภทข้อมูลที่เข้ากันได้) ดูตัวอย่าง ด้านล่าง:

PRINT COALESCE(NULL, ('str-'+'1'), 'x')  --returns 'str-1, works as all args (excluding NULLs) are of same VARCHAR type.
--PRINT COALESCE(NULL, 'text', '3', 3)    --ERROR: passed args are NOT matching type / can't be implicitly converted.
PRINT COALESCE(NULL, 3, 7.0/2, 1.99)      --returns 3.0, works fine as implicit conversion into FLOAT type takes place.
PRINT COALESCE(NULL, '1995-01-31', 'str') --returns '2018-11-16', works fine as implicit conversion into VARCHAR occurs.

DECLARE @dt DATE = getdate()
PRINT COALESCE(NULL, @dt, '1995-01-31')  --returns today's date, works fine as implicit conversion into DATE type occurs.

--DATE comes before VARCHAR (works):
PRINT COALESCE(NULL, @dt, 'str')      --returns '2018-11-16', works fine as implicit conversion of Date into VARCHAR occurs.

--VARCHAR comes before DATE (does NOT work):
PRINT COALESCE(NULL, 'str', @dt)      --ERROR: passed args are NOT matching type, can't auto-cast 'str' into Date type.

HTH


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