Mengatasi Isu Pernyataan KES dalam SQL Server 2008 WHERE Klausa
Menggunakan pernyataan CASE dalam klausa WHERE dalam SQL Server 2008 boleh menimbulkan kesukaran. Pertanyaan berikut menunjukkan masalah biasa:
<code class="language-sql">SELECT tl.storenum 'Store #', co.ccnum 'FuelFirst Card #', co.dtentered 'Date Entered', CASE st.reasonid WHEN 1 THEN 'Active' WHEN 2 THEN 'Not Active' WHEN 0 THEN st.ccstatustypename ELSE 'Unknown' END 'Status', CASE st.ccstatustypename WHEN 'Active' THEN ' ' WHEN 'Not Active' THEN ' ' ELSE st.ccstatustypename END 'Reason', UPPER(REPLACE(REPLACE(co.personentered,'RT\\',''),'RACETRAC\\','')) 'Person Entered', co.comments 'Comments or Notes' FROM comments co INNER JOIN cards cc ON co.ccnum=cc.ccnum INNER JOIN customerinfo ci ON cc.customerinfoid=ci.customerinfoid INNER JOIN ccstatustype st ON st.ccstatustypeid=cc.ccstatustypeid INNER JOIN customerstatus cs ON cs.customerstatuscd=ci.customerstatuscd INNER JOIN transactionlog tl ON tl.transactionlogid=co.transactionlogid LEFT JOIN stores s ON s.StoreNum = tl.StoreNum WHERE CASE LEN('TestPerson') WHEN 0 THEN co.personentered = co.personentered ELSE co.personentered LIKE '%TestPerson' END AND cc.ccnum = CASE LEN('TestFFNum') WHEN 0 THEN cc.ccnum ELSE 'TestFFNum' END AND CASE LEN('2011-01-09 11:56:29.327') WHEN 0 THEN co.DTEntered = co.DTEntered ELSE CASE LEN('2012-01-09 11:56:29.327') WHEN 0 THEN co.DTEntered >= '2011-01-09 11:56:29.327' ELSE co.DTEntered BETWEEN '2011-01-09 11:56:29.327' AND '2012-01-09 11:56:29.327' END END AND tl.storenum < 699 ORDER BY tl.StoreNum</code>
Penyelesaian: Pemfaktoran Semula dengan Logik Boolean
Isu teras terletak pada penggunaan pernyataan CASE yang tidak sesuai secara langsung dalam logik bersyarat klausa WHERE. Ungkapan CASE harus menghasilkan nilai; ia tidak sepatutnya menjadi keseluruhan syarat.
Penyelesaian melibatkan menggantikan pernyataan CASE dengan logik boolean yang setara menggunakan operator AND
dan OR
:
<code class="language-sql">SELECT tl.storenum 'Store #', co.ccnum 'FuelFirst Card #', co.dtentered 'Date Entered', CASE st.reasonid WHEN 1 THEN 'Active' WHEN 2 THEN 'Not Active' WHEN 0 THEN st.ccstatustypename ELSE 'Unknown' END 'Status', CASE st.ccstatustypename WHEN 'Active' THEN ' ' WHEN 'Not Active' THEN ' ' ELSE st.ccstatustypename END 'Reason', UPPER(REPLACE(REPLACE(co.personentered,'RT\\',''),'RACETRAC\\','')) 'Person Entered', co.comments 'Comments or Notes' FROM comments co INNER JOIN cards cc ON co.ccnum=cc.ccnum INNER JOIN customerinfo ci ON cc.customerinfoid=ci.customerinfoid INNER JOIN ccstatustype st ON st.ccstatustypeid=cc.ccstatustypeid INNER JOIN customerstatus cs ON cs.customerstatuscd=ci.customerstatuscd INNER JOIN transactionlog tl ON tl.transactionlogid=co.transactionlogid LEFT JOIN stores s ON s.StoreNum = tl.StoreNum WHERE (LEN('TestPerson') = 0 AND co.personentered = co.personentered) OR (LEN('TestPerson') > 0 AND co.personentered LIKE '%TestPerson') AND ((LEN('TestFFNum') = 0 AND cc.ccnum = cc.ccnum) OR (LEN('TestFFNum') > 0 AND cc.ccnum = 'TestFFNum')) AND ((LEN('2011-01-09 11:56:29.327') = 0 AND co.DTEntered = co.DTEntered) OR (LEN('2012-01-09 11:56:29.327') = 0 AND co.DTEntered >= '2011-01-09 11:56:29.327') OR (co.DTEntered BETWEEN '2011-01-09 11:56:29.327' AND '2012-01-09 11:56:29.327')) AND tl.storenum < 699 ORDER BY tl.StoreNum;</code>
Peningkatan Prestasi
Sementara pertanyaan yang diperbetulkan ini berfungsi dengan betul, prestasi boleh dipertingkatkan lagi:
OR
bersarang dalam boleh menjadi kurang cekap. Pertimbangkan struktur pertanyaan alternatif (cth., menggunakan UNION ALL
untuk kriteria carian yang berbeza).WHERE
(cth., co.personentered
, cc.ccnum
, co.DTEntered
, tl.storenum
).Dengan menangani perkara ini, anda boleh mencipta pertanyaan SQL yang lebih cekap dan boleh dibaca.
Atas ialah kandungan terperinci Bagaimanakah Saya Boleh Menggunakan Pernyataan CASE Dengan Betul dalam Klausa WHERE dalam SQL Server 2008?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!