137 votes

"CASE" statement dans la clause "WHERE" dans SQL Server 2008

Je travaille avec une requête qui contient une déclaration "CASE" dans la clause "WHERE". Mais SQL Server 2008 renvoie des erreurs lors de son exécution. Est-ce que quelqu'un pourrait m'aider avec la requête correcte ? Voici la requête :

SELECT
    tl.storenum 'Store #', 
    co.ccnum 'FuelFirst Card #', 
    co.dtentered 'Date Entered',
    CASE st.reasonid 
        WHEN 1 THEN 'Actif' 
   WHEN 2 THEN 'Non actif' 
   WHEN 0 THEN st.ccstatustypename 
   ELSE 'Inconnu' 
    END 'Statut',
    CASE st.ccstatustypename 
        WHEN 'Actif' THEN ' ' 
   WHEN 'Non actif' THEN ' ' 
   ELSE st.ccstatustypename 
    END 'Raison',
    UPPER(REPLACE(REPLACE(co.personentered,'RT\\\\',''),'RACETRAC\\\\','')) 'Personne entrée',
    co.comments 'Commentaires ou 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

2 votes

Cas d'expression, pas d'instruction... (La case d'expression renvoie une valeur. La case d'instruction est utilisée dans les procédures stockées pour l'exécution conditionnelle du code.)

259voto

Code Magician Points 8724

Tout d'abord, l'instruction CASE doit faire partie de l'expression, pas l'expression elle-même.

En d'autres termes, vous pouvez avoir:

WHERE co.DTEntered = CASE 
                          WHEN LEN('blah') = 0 
                               THEN co.DTEntered 
                          ELSE '2011-01-01' 
                     END 

Mais cela ne fonctionnera pas comme vous les avez écrits, par exemple :

WHERE 
    CASE LEN('TestPerson')
        WHEN 0 THEN co.personentered  = co.personentered
   ELSE co.personentered LIKE '%TestPerson'
    END 

Vous aurez peut-être plus de chance en utilisant des déclarations OR combinées comme ceci :

WHERE (
        (LEN('TestPerson') = 0 
             AND co.personentered = co.personentered
        ) 
        OR 
        (LEN('TestPerson') <> 0 
             AND co.personentered LIKE '%TestPerson')
      )

Cependant, je ne sais pas quel plan de requête vous obtiendrez de cette manière. Ce genre de manigances dans une clause WHERE empêchera souvent l'optimiseur de requête d'utiliser des index.

22voto

janak magotra Points 31

Essayez ce qui suit :

SELECT * FROM emp_master 
WHERE emp_last_name= 
CASE emp_first_name 
 WHEN 'test'    THEN 'test' 
 WHEN 'M. nom' THEN 'nom'
END

16voto

Sajib Mahmud Points 129

Cela devrait résoudre votre problème pour le moment mais je dois vous rappeler que ce n'est pas une bonne approche :

WHERE 
            CASE LEN('TestPerson')
                WHEN 0 THEN 
                        CASE WHEN co.personentered  = co.personentered THEN 1 ELSE 0 END
                ELSE 
                        CASE WHEN co.personentered LIKE '%TestPerson' THEN 1 ELSE 0 END
            END = 1
        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 CASE WHEN co.DTEntered = co.DTEntered THEN 1 ELSE 0 END 
                ELSE 
                    CASE LEN('2012-01-09 11:56:29.327') 
                        WHEN 0 THEN 
                            CASE WHEN co.DTEntered >= '2011-01-09 11:56:29.327' THEN 1 ELSE 0 END 
                        ELSE 
                            CASE WHEN co.DTEntered BETWEEN '2011-01-09 11:56:29.327' 
                                                        AND '2012-01-09 11:56:29.327' 
                                                     THEN 1 ELSE 0 END
                    END
            END = 1
        AND tl.storenum < 699

8voto

Oleg Dok Points 12155

Je pense que le début de votre requête devrait ressembler à ceci :

SELECT
    tl.storenum [Numéro de magasin], 
    co.ccnum [N° de carte FuelFirst], 
    co.dtentered [Date entrée],
    CASE st.reasonid 
        WHEN 1 THEN 'Actif' 
        WHEN 2 THEN 'Non actif' 
        WHEN 0 THEN st.ccstatustypename 
        ELSE 'Inconnu' 
    END [Statut],
    CASE st.ccstatustypename 
        WHEN 'Actif' THEN ' ' 
        WHEN 'Non actif' THEN ' ' 
        ELSE st.ccstatustypename 
        END [Raison],
    UPPER(REPLACE(REPLACE(co.personentered,'RT\\\\',''),'RACETRAC\\\\','')) [Personne qui a entré],
    co.comments [Commentaires ou 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 
      WHEN (LEN([TestPerson]) = 0 AND co.personentered  = co.personentered) OR (LEN([TestPerson]) <> 0 AND co.personentered LIKE '%'+TestPerson) THEN 1
      ELSE 0
      END = 1
    AND 

MAIS

ce qui se trouve à la fin est complètement incompréhensible

4voto

MnemosyneD Points 41

La partie WHERE pourrait être écrite comme suit :

WHERE 
 (LEN('TestPerson') <> 0 OR co.personentered  = co.personentered) AND
 (LEN('TestPerson') = 0 OR co.personentered LIKE '%TestPerson') AND
 (cc.ccnum = CASE LEN('TestFFNum')
                WHEN 0 THEN cc.ccnum 
                ELSE 'TestFFNum' 
              END ) AND
 (LEN('2011-01-09 11:56:29.327') <> 0 OR co.DTEntered = co.DTEntered ) AND
 ((LEN('2011-01-09 11:56:29.327') = 0 AND LEN('2012-01-09 11:56:29.327') <> 0) OR co.DTEntered >= '2011-01-09 11:56:29.327'  ) AND
 ((LEN('2011-01-09 11:56:29.327') = 0 AND LEN('2012-01-09 11:56:29.327') = 0) OR co.DTEntered BETWEEN '2011-01-09 11:56:29.327' AND '2012-01-09 11:56:29.327'  ) AND 
 tl.storenum < 699

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X