Menggunakan KASUS yang Sama KAPAN Kondisi Untuk Beberapa Kolom Permintaan

12

Apakah ada cara "lebih baik" untuk menulis ulang SELECTklausa di mana beberapa kolom menggunakan CASE WHENkondisi yang sama sehingga kondisi hanya diperiksa satu kali?

Lihat contoh di bawah ini.

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

Dalam kode psuedo non-sql, kode tersebut mungkin terlihat seperti:

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

catatan:

  • Saya menyadari masalah normalisasi yang ditunjukkan oleh kueri. Saya hanya ingin menunjukkan masalahnya.
Steven
sumber
Dan semua kolom ini authTime, authUser, cmplTimeberada di meja yang sama?
ypercubeᵀᴹ
pertanyaan serupa: stackoverflow.com/q/13713316/4632019
Eugen Konkov

Jawaban:

7

Bahkan di Oracle (dan bahkan dalam standar SQL), CASEadalah ekspresi yang mengembalikan nilai tunggal. Itu tidak digunakan untuk kontrol aliran seperti di beberapa bahasa lain. Oleh karena itu, tidak dapat digunakan untuk memutuskan secara kondisional di antara beberapa kolom atau operasi lainnya.

Saya akan mengatakan meletakkan versi kode yang lebih panjang (yang sudah berfungsi) dalam tampilan, dan jangan khawatir tentang hal itu dalam permintaan formal Anda.

Anda mungkin juga mempertimbangkan desain yang lebih normal. Misalnya mengapa tidak menyimpan dia mengaudit detail di tabel terpisah, dengan tipe sebagai bagian dari kunci? Ini membuat kode Anda lebih mudah dipelihara, terutama karena lebih banyak jenis ditambahkan ...

Aaron Bertrand
sumber
Even in Oracle... tetapi dalam Postgres itu mungkin dengan memperluas tipe komposit.
Eugen Konkov
7

Jika semua kolom ini dari tabel yang sama, Anda dapat menggunakan sesuatu seperti ini:

    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' ;
ypercubeᵀᴹ
sumber
2
Saya merenungkan posting itu, tapi itu sama bertele-tele. Saya tidak berpikir ada cara yang baik untuk melakukannya.
Philᵀᴹ
Itu menjawab pertanyaan +1, tetapi seperti yang telah ditunjukkan orang lain, apa yang Anda mulai dengan lebih baik. Anda juga bisa menggabungkan nilai-nilai yang sesuai dengan masing-masing testStatus dan kemudian membaginya, tetapi itu akan lebih buruk lagi.
Leigh Riffel