web-dev-qa-db-fra.com

Clause SQL Switch / Case dans la clause 'Where'

J'ai essayé de chercher, mais je n'ai rien trouvé qui puisse m'aider.

J'essaie de faire cela en SQL:

declare @locationType varchar(50);
declare @locationID int;

SELECT column1, column2
FROM viewWhatever
WHERE
CASE @locationType
    WHEN 'location' THEN account_location = @locationID
    WHEN 'area' THEN xxx_location_area = @locationID
    WHEN 'division' THEN xxx_location_division = @locationID

Je sais que je ne devrais pas avoir à mettre '= @locationID' à la fin de chacun, mais je ne parviens pas à obtenir une syntaxe proche de la vérité. SQL n'arrête pas de se plaindre de mon '=' sur la première ligne WHEN ...

Comment puis-je faire ceci?

141
Miles
declare @locationType varchar(50);
declare @locationID int;

SELECT column1, column2
FROM viewWhatever
WHERE
@locationID = 
  CASE @locationType
      WHEN 'location' THEN account_location
      WHEN 'area' THEN xxx_location_area 
      WHEN 'division' THEN xxx_location_division 
  END
186
Bob Probst

sans déclaration de cas ...

SELECT column1, column2
FROM viewWhatever
WHERE
    (@locationType = 'location' AND account_location = @locationID)
    OR
    (@locationType = 'area' AND xxx_location_area = @locationID)
    OR
    (@locationType = 'division' AND xxx_location_division = @locationID)
69
Lukek

Voici.

SELECT
   column1, 
   column2
FROM
   viewWhatever
WHERE
CASE 
    WHEN @locationType = 'location' AND account_location = @locationID THEN 1
    WHEN @locationType = 'area' AND xxx_location_area = @locationID THEN 1
    WHEN @locationType = 'division' AND xxx_location_division = @locationID THEN 1
    ELSE 0
END = 1
32
Pittsburgh DBA

Je dirais que ceci est un indicateur d'une structure de table défectueuse. Peut-être que les différents types d’emplacement devraient être séparés dans différentes tables, ce qui vous permettra d’effectuer des requêtes beaucoup plus riches et d’éviter la présence de colonnes superflues.

Si vous ne parvenez pas à modifier la structure, les opérations ci-dessous peuvent fonctionner:

SELECT
    *
FROM
    Test
WHERE
    Account_Location = (
        CASE LocationType
          WHEN 'location' THEN @locationID
          ELSE Account_Location
        END
    )
    AND
    Account_Location_Area = (
        CASE LocationType
          WHEN 'area' THEN @locationID
          ELSE Account_Location_Area
        END
    )

Et ainsi de suite ... Nous ne pouvons pas changer la structure de la requête à la volée, mais nous pouvons la remplacer en rendant les prédicats égaux.

EDIT: Les suggestions ci-dessus sont bien sûr beaucoup mieux, ignorez simplement les miennes.

6
Mark S. Rasmussen

OU opérateur peut être alternative au cas où dans la condition

ALTER PROCEDURE [dbo].[RPT_340bClinicDrugInventorySummary]
    -- Add the parameters for the stored procedure here
     @ClinicId BIGINT = 0,
     @selecttype int,
     @selectedValue varchar (50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
SELECT
    drugstock_drugname.n_cur_bal,drugname.cdrugname,clinic.cclinicname

FROM drugstock_drugname
INNER JOIN drugname ON drugstock_drugname.drugnameid_FK = drugname.drugnameid_PK
INNER JOIN drugstock_drugndc ON drugname.drugnameid_PK = drugstock_drugndc.drugnameid_FK
INNER JOIN drugndc ON drugstock_drugndc.drugndcid_FK = drugndc.drugid_PK
LEFT JOIN clinic ON drugstock_drugname.clinicid_FK = clinic.clinicid_PK

WHERE   (@ClinicId = 0 AND 1 = 1)
    OR  (@ClinicId != 0 AND drugstock_drugname.clinicid_FK = @ClinicId)

    -- Alternative Case When You can use OR
    AND ((@selecttype = 1 AND 1 = 1)
    OR  (@selecttype = 2 AND drugname.drugnameid_PK = @selectedValue)
    OR  (@selecttype = 3 AND drugndc.drugid_PK = @selectedValue)
    OR  (@selecttype = 4 AND drugname.cdrugclass = 'C2')
    OR  (@selecttype = 5 AND LEFT(drugname.cdrugclass, 1) = 'C'))

ORDER BY clinic.cclinicname, drugname.cdrugname
END
5
atik sarker

Le problème est que, lorsque le moteur SQL évalue l'expression, il vérifie la partie FROM pour extraire les tables appropriées, puis la partie WHERE pour fournir certains critères de base, de sorte qu'il ne peut pas évaluer correctement une condition dynamique dans laquelle colonne vérifier contre.

Vous pouvez utiliser une clause WHERE lorsque vous vérifiez les critères WHERE dans le prédicat, tels que

WHERE account_location = CASE @locationType
                              WHEN 'business' THEN 45
                              WHEN 'area' THEN 52
                         END

par conséquent, dans votre cas particulier, vous devrez insérer la requête dans une procédure stockée ou créer trois requêtes distinctes.

5
Dillie-O

S'il vous plaît essayez cette requête. Répondre au message ci-dessus:

select @msgID, account_id
    from viewMailAccountsHeirachy
    where 
    CASE @smartLocationType
        WHEN 'store' THEN account_location
        WHEN 'area' THEN xxx_location_area 
        WHEN 'division' THEN xxx_location_division 
        WHEN 'company' THEN xxx_location_company 
    END  = @smartLocation
3
Durre Najaf

Essaye ça:

WHERE (
    @smartLocationType IS NULL 
    OR account_location = (
         CASE
            WHEN @smartLocationType IS NOT NULL 
                 THEN @smartLocationType
            ELSE account_location 
         END
    )
)
2
shah134pk