Heim >Datenbank >MySQL-Tutorial >Wie kann ich CASE-Anweisungen in WHERE-Klauseln in SQL Server 2008 korrekt verwenden?
Behebung von CASE-Anweisungsproblemen in SQL Server 2008 WHERE-Klauseln
Die Verwendung von CASE-Anweisungen innerhalb von WHERE-Klauseln in SQL Server 2008 kann Schwierigkeiten bereiten. Die folgende Abfrage veranschaulicht ein häufiges Problem:
<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>
Die Lösung: Refactoring mit Boolescher Logik
Das Kernproblem liegt in der unangemessenen Verwendung von CASE-Anweisungen direkt innerhalb der bedingten Logik der WHERE-Klausel. CASE-Ausdrücke sollten einen Wert erzeugen; Sie sollten nicht den gesamten Zustand ausmachen.
Die Lösung besteht darin, die CASE-Anweisungen durch eine entsprechende boolesche Logik unter Verwendung der Operatoren AND
und OR
zu ersetzen:
<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>
Leistungsverbesserungen
Während diese korrigierte Abfrage ordnungsgemäß funktioniert, kann die Leistung weiter verbessert werden:
OR
Bedingungen können weniger effizient sein. Erwägen Sie alternative Abfragestrukturen (z. B. die Verwendung von UNION ALL
für eindeutige Suchkriterien).WHERE
-Klauseln verwendet werden (z. B. co.personentered
, cc.ccnum
, co.DTEntered
, tl.storenum
).Indem Sie diese Punkte berücksichtigen, können Sie eine effizientere und lesbarere SQL-Abfrage erstellen.
Das obige ist der detaillierte Inhalt vonWie kann ich CASE-Anweisungen in WHERE-Klauseln in SQL Server 2008 korrekt verwenden?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!