ใช้กรณีเดียวกันเมื่อเงื่อนไขสำหรับคอลัมน์แบบสอบถามจำนวนมาก


12

มีวิธี "ดีกว่า" ในการเขียนSELECTประโยคใหม่ที่มีคอลัมน์จำนวนมากใช้CASE WHENเงื่อนไขเดียวกันเพื่อให้มีการตรวจสอบเงื่อนไขเพียงครั้งเดียวหรือไม่

ดูตัวอย่างด้านล่าง

SELECT
    CASE testStatus 
        WHEN 'A' THEN 'Authorized'
        WHEN 'C' THEN 'Completed'
        WHEN 'P' THEN 'In Progress'
        WHEN 'X' THEN 'Cancelled'
    END AS Status,

    CASE testStatus 
        WHEN 'A' THEN authTime
        WHEN 'C' THEN cmplTime
        WHEN 'P' THEN strtTime
        WHEN 'X' THEN cancTime
    END AS lastEventTime,

    CASE testStatus 
        WHEN 'A' THEN authBy
        WHEN 'C' THEN cmplBy
        WHEN 'P' THEN strtBy
        WHEN 'X' THEN cancBy
    END AS lastEventUser
FROM test

ในโค้ด psuedo ที่ไม่ใช่ sql โค้ดอาจมีลักษณะดังนี้:

CASE testStatus
    WHEN 'A'
        StatusCol        = 'Authorized'
        lastEventTimeCol = authTime 
        lastEventUserCol = authUser
    WHEN 'C'
        StatusCol        = 'Completed'
        lastEventTimeCol = cmplTime
        lastEventUserCol = cmplUser
    ...
END

บันทึก:

  • ฉันตระหนักถึงปัญหาการนอร์มัลไลซ์ที่เห็นได้ชัดโดยนัยจากการสืบค้น ฉันแค่ต้องการแสดงให้เห็นถึงปัญหา

และคอลัมน์ทั้งหมดเหล่านี้authTime, authUser, cmplTimeอยู่ในโต๊ะเดียวกันได้หรือไม่
ypercubeᵀᴹ

คำถามที่คล้ายกัน: stackoverflow.com/q/13713316/4632019
Eugen Konkov

คำตอบ:


7

แม้แต่ใน Oracle (และในความเป็นจริงในมาตรฐาน SQL) CASEคือนิพจน์ที่ส่งคืนค่าเดียว มันไม่ได้ใช้สำหรับการควบคุมการไหลเหมือนในภาษาอื่น ๆ ดังนั้นจึงไม่สามารถใช้ในการตัดสินใจแบบมีเงื่อนไขในหลายคอลัมน์หรือการดำเนินการอื่น ๆ

ฉันจะบอกว่าให้ใส่รหัสรุ่นที่ยาวขึ้น (ซึ่งใช้งานได้แล้ว) ในมุมมองและไม่ต้องกังวลกับมันในการสืบค้นที่เป็นทางการของคุณ

คุณอาจพิจารณาการออกแบบที่เป็นมาตรฐานมากขึ้น ตัวอย่างเช่นทำไมไม่จัดเก็บเขาตรวจสอบรายละเอียดในตารางแยกประเภทเป็นส่วนหนึ่งของคีย์? ทำให้รหัสของคุณง่ายต่อการบำรุงรักษาโดยเฉพาะอย่างยิ่งเมื่อมีการเพิ่มประเภทอื่น ๆ ...


Even in Oracle... แต่ใน Postgres ที่เป็นไปได้โดยการขยายประเภทคอมโพสิต
Eugen Konkov

7

หากคอลัมน์ทั้งหมดเหล่านี้มาจากตารางเดียวกันคุณสามารถใช้สิ่งนี้:

    SELECT  
        'Authorized' AS StatusCol,
        authTime     AS lastEventTimeCol, 
        authUser     AS lastEventUserCol 
    FROM test
    WHERE testStatus = 'A'

  UNION ALL

    SELECT  
        'Completed', 
        cmplTime,
        cmplUser    
    FROM test
    WHERE testStatus = 'C'

  UNION ALL

    SELECT  
        'In Progress', 
        strtTime,
        strtUser    
    FROM test
    WHERE testStatus = 'P'

  UNION ALL

    SELECT  
        'Cancelled', 
        cancTime,
        cancUser    
    FROM test
    WHERE testStatus = 'X' ;

2
ฉันไตร่ตรองการโพสต์นั้น แต่มันก็ยืดเยื้อ ฉันไม่คิดว่าจะมีวิธีที่ดีในการทำมัน
Philᵀᴹ

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