วิธีที่ดีที่สุดที่จะทำตรรกะคำสั่งกรณีที่ซ้อนกันใน SQL Server


185

ฉันกำลังเขียน SQL Query โดยที่คอลัมน์จำนวนหนึ่งที่ส่งคืนนั้นจำเป็นต้องคำนวณขึ้นอยู่กับเงื่อนไขค่อนข้างมาก

ฉันกำลังใช้งบกรณีที่ซ้อนกัน แต่มันยุ่งเหยิง มีวิธีที่ดีกว่า (จัดระเบียบมากขึ้นและ / หรืออ่านได้)?

(ฉันใช้ Microsoft SQL Server, 2005)


ตัวอย่างง่าย ๆ :

SELECT
    col1,
    col2,
    col3,
    CASE
        WHEN condition 
        THEN
            CASE
                WHEN condition1 
                THEN
                    CASE 
                        WHEN condition2
                        THEN calculation1
                        ELSE calculation2
                    END
                ELSE
                    CASE 
                        WHEN condition2
                        THEN calculation3
                        ELSE calculation4
                    END
            END
        ELSE 
            CASE 
                WHEN condition1 
                THEN 
                    CASE
                        WHEN condition2 
                        THEN calculation5
                        ELSE calculation6
                    END
                ELSE
                    CASE
                        WHEN condition2 
                        THEN calculation7
                        ELSE calculation8
                    END
            END            
    END AS 'calculatedcol1',
    col4,
    col5 -- etc
FROM table

สวัสดีคุณใช้เครื่องมือ (เช่น SQLinForm) เพื่อเยื้องการสืบค้นที่ซ้อนกันหรือเปล่า?
กุยโด้

ขอบคุณที่คุณสอนวิธีการจัดรูปแบบที่ดีกว่าสำหรับซ้อนกันCASE WHEN
Simon1979

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

คำตอบ:


188

คุณสามารถลองใช้เคล็ดลับ COALESCE เช่น:

เลือก COALESCE (
  กรณีที่เงื่อนไข 1 จากนั้นการคำนวณ 1 อื่น ๆ สิ้นสุด,
  กรณีที่เงื่อนไข 2 จากนั้นคำนวณ 2 อื่น ๆ สิ้นสุด,
  ฯลฯ ...
)

ดีฉันเพิ่งทดสอบเพื่อให้แน่ใจว่ามันลัดวงจรและประหลาดใจที่พบว่ามันทำ ดังนั้นหาก condition1 ตรวจสอบหารด้วยศูนย์จะปรากฏว่าปลอดภัยที่จะทำใน condition2 ไม่แน่ใจว่าสิ่งนี้รับประกันหรือไม่
Cade Roux

13
One catch คือถ้าหนึ่งในคดีของคุณต้องการคืนค่า NULL อย่างถูกกฎหมายคุณจะไม่สามารถทำได้
Chris KL

8
นี่เป็นกลอุบายที่ยอดเยี่ยม แต่โปรดจำไว้ว่ามันอาจทำงานได้ไม่ดีเช่นเดียวกับการใช้คำสั่ง CASE เพียงอย่างเดียว นี้คือ "เอกสาร" ในส่วนของชุมชนเพิ่มขึ้นที่นี่ - msdn.microsoft.com/en-us/library/ms190349.aspx DBA ของฉันเพียงแค่ใส่ค้อนลงเมื่อผมดำเนินการแก้ปัญหานี้ ...
shanabus

เมื่อไรจะดีกว่าคำสั่ง case (คำตอบของ @ beach)
Ronnie Overby

วิธีการเปลี่ยนชื่อคอลัมน์ในคำตอบนี้ .. เช่นถ้าฉันต้องการเปลี่ยนชื่อ 'calcul1' เป็น 'CAL1' ... มันเป็นไปได้อย่างไรในการสร้างประโยค
Renascent

89

ห่อกรณีเหล่านั้นทั้งหมดไว้ในที่เดียว


SELECT
    col1,
    col2,
    col3,
    CASE
        WHEN condition1 THEN calculation1 
        WHEN condition2 THEN calculation2
        WHEN condition3 THEN calculation3
        WHEN condition4 THEN calculation4
        WHEN condition5 THEN calculation5
        ELSE NULL         
    END AS 'calculatedcol1',
    col4,
    col5 -- etc
FROM table

31

คุณสามารถรวมหลายเงื่อนไขเพื่อหลีกเลี่ยงสถานการณ์:

CASE WHEN condition1 = true AND condition2 = true THEN calculation1 
     WHEN condition1 = true AND condition2 = false 
     ELSE 'what so ever' END,

21

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

SELECT
    col1,
    col2,
    col3,
    CASE WHEN condition THEN
      CASE WHEN condition1 THEN
        CASE WHEN condition2 THEN calculation1
        ELSE calculation2 END
      ELSE
        CASE WHEN condition2 THEN calculation3
        ELSE calculation4 END
      END
    ELSE CASE WHEN condition1 THEN 
      CASE WHEN condition2 THEN calculation5
      ELSE calculation6 END
    ELSE CASE WHEN condition2 THEN calculation7
         ELSE calculation8 END
    END AS 'calculatedcol1',
    col4,
    col5 -- etc
FROM table

11

ต่อไปนี้เป็นวิธีแก้ไขปัญหาแบบง่าย ๆ สำหรับกรณีของ "Complex": - Nested Case Complex Expression

select  datediff(dd,Invdate,'2009/01/31')+1 as DaysOld, 
    case when datediff(dd,Invdate,'2009/01/31')+1 >150 then 6 else
        case when datediff(dd,Invdate,'2009/01/31')+1 >120 then 5 else 
            case when datediff(dd,Invdate,'2009/01/31')+1 >90 then 4 else 
                case when datediff(dd,Invdate,'2009/01/31')+1 >60 then 3 else 
                    case when datediff(dd,Invdate,'2009/01/31')+1 >30 then 2 else 
                        case when datediff(dd,Invdate,'2009/01/31')+1 >30 then 1 end 
                    end
                end
            end
        end
    end as Bucket
from rm20090131atb

เพียงให้แน่ใจว่าคุณมีคำสั่งสิ้นสุดสำหรับทุกคำสั่งกรณี


5
คุณอาจต้องการจัดรูปแบบคำตอบหากคุณต้องการให้คนอื่นอ่าน
IsmailS

6

เราสามารถรวมหลายเงื่อนไขเข้าด้วยกันเพื่อลดค่าใช้จ่ายด้านประสิทธิภาพ

ให้มีสามตัวแปร abc ที่เราต้องการดำเนินการกรณีและปัญหา เราสามารถทำได้ดังนี้:

CASE WHEN a = 1 AND b = 1 AND c = 1 THEN '1'
     WHEN a = 0 AND b = 0 AND c = 1 THEN '0'
ELSE '0' END,

5

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


2

ฉันผ่านขั้นตอนนี้และพบคำตอบทั้งหมดยอดเยี่ยม แต่ต้องการเพิ่มคำตอบที่ @deejers ให้

    SELECT
    col1,
    col2,
    col3,
    CASE
        WHEN condition1 THEN calculation1 
        WHEN condition2 THEN calculation2
        WHEN condition3 THEN calculation3
        WHEN condition4 THEN calculation4
        WHEN condition5 THEN calculation5         
    END AS 'calculatedcol1',
    col4,
    col5 -- etc
FROM table

คุณสามารถกำหนดให้ ELSE เป็นตัวเลือกเนื่องจากไม่จำเป็นมันมีประโยชน์มากในหลาย ๆ สถานการณ์


2

ตัวอย่างนี้อาจช่วยคุณได้รูปภาพแสดงลักษณะของคำสั่ง SQL case ที่ดูเหมือนว่าจะเกิดอะไรขึ้นถ้ามีวงวนภายในมากกว่าหนึ่งวง

ป้อนคำอธิบายรูปภาพที่นี่

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