Heim > Datenbank > MySQL-Tutorial > Wie kann ich CASE-Anweisungen in WHERE-Klauseln in SQL Server 2008 korrekt verwenden?

Wie kann ich CASE-Anweisungen in WHERE-Klauseln in SQL Server 2008 korrekt verwenden?

Mary-Kate Olsen
Freigeben: 2025-01-11 09:54:42
Original
772 Leute haben es durchsucht

How Can I Correctly Use CASE Statements Within WHERE Clauses in SQL Server 2008?

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>
Nach dem Login kopieren

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>
Nach dem Login kopieren

Leistungsverbesserungen

Während diese korrigierte Abfrage ordnungsgemäß funktioniert, kann die Leistung weiter verbessert werden:

  • Verschachtelung reduzieren: Die tief verschachtelten OR Bedingungen können weniger effizient sein. Erwägen Sie alternative Abfragestrukturen (z. B. die Verwendung von UNION ALL für eindeutige Suchkriterien).
  • Indizierung: Stellen Sie sicher, dass Indizes für Spalten vorhanden sind, die häufig in WHERE-Klauseln verwendet werden (z. B. co.personentered, cc.ccnum, co.DTEntered, tl.storenum).
  • Parametrierung: Wenn es sich bei diesen „Test“-Werten um Variablen handelt, verwenden Sie parametrisierte Abfragen, um eine wiederholte Abfrageanalyse zu vermeiden.

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!

Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage