188 votes

Puis-je utiliser l'instruction CASE dans une condition JOIN ?

L'image suivante fait partie de Microsoft SQL Server 2008 R2 System Views. Sur cette image, nous pouvons voir que la relation entre sys.partitions y sys.allocation_units dépend de la valeur de sys.allocation_units.type . Pour les réunir, j'écrirais donc quelque chose de semblable à ceci :

SELECT  *
FROM    sys.indexes i
        JOIN sys.partitions p
            ON i.index_id = p.index_id 
        JOIN sys.allocation_units a
            ON CASE
               WHEN a.type IN (1, 3)
                   THEN a.container_id = p.hobt_id 
               WHEN a.type IN (2)
                   THEN a.container_id = p.partition_id
               END 

Mais le code supérieur donne une erreur de syntaxe. Je suppose que c'est à cause du CASE déclaration. Quelqu'un peut-il m'aider à expliquer un peu ?


Ajouter un message d'erreur :

Msg 102, Level 15, State 1, Line 6 Syntaxe incorrecte près de '='.

this is the image

305voto

HABO Points 5878

A CASE renvoie une valeur de l'expression THEN de la clause. Vous pouvez l'utiliser de la manière suivante :

SELECT  * 
FROM    sys.indexes i 
    JOIN sys.partitions p 
        ON i.index_id = p.index_id  
    JOIN sys.allocation_units a 
        ON CASE 
           WHEN a.type IN (1, 3) AND a.container_id = p.hobt_id THEN 1
           WHEN a.type IN (2) AND a.container_id = p.partition_id THEN 1
           ELSE 0
           END = 1

Notez que vous devez faire quelque chose avec la valeur renvoyée, par exemple la comparer à 1. Votre déclaration tentait de renvoyer la valeur d'une affectation ou de tester l'égalité, ce qui n'a aucun sens dans le contexte d'un CASE / THEN clause. (Si BOOLEAN était un type de données, le test d'égalité aurait un sens).

58voto

Niranjan Kala Points 9739

Au lieu de cela, vous joignez simplement les deux tables, et dans votre clause SELECT, renvoyer les données de la table qui correspond :

Je vous suggère de consulter ce lien Joints conditionnels dans SQL Server y Déclaration de cas T-SQL dans une clause JOIN ON

par exemple

    SELECT  *
FROM    sys.indexes i
        JOIN sys.partitions p
            ON i.index_id = p.index_id 
        JOIN sys.allocation_units a
            ON a.container_id =
            CASE
               WHEN a.type IN (1, 3)
                   THEN  p.hobt_id 
               WHEN a.type IN (2)
                   THEN p.partition_id
               END 

Edit : Comme indiqué dans les commentaires.

Vous ne pouvez pas spécifier la condition de jointure comme vous le faites. Vérifiez la la requête ci-dessus qui n'a pas d'erreur. J'ai supprimé la colonne commune up et la valeur de la colonne de droite sera évaluée en fonction de la condition.

18voto

richardtallent Points 17534

Essayez ceci :

...JOIN sys.allocation_units a ON 
  (a.type=2 AND a.container_id = p.partition_id)
  OR (a.type IN (1, 3) AND a.container_id = p.hobt_id)

11voto

DonkeyKong Points 441

Je pense que vous avez besoin de deux déclarations de cas :

SELECT  *
FROM    sys.indexes i
    JOIN sys.partitions p
        ON i.index_id = p.index_id 
    JOIN sys.allocation_units a
        ON 
        -- left side of join on statement
            CASE
               WHEN a.type IN (1, 3)
                   THEN a.container_id
               WHEN a.type IN (2)
                   THEN a.container_id
            END 
        = 
        -- right side of join on statement
            CASE
               WHEN a.type IN (1, 3)
                   THEN p.hobt_id
               WHEN a.type IN (2)
                   THEN p.partition_id
            END             

En effet :

  • l'instruction CASE renvoie une seule valeur à l'END

  • l'instruction ON compare deux valeurs

  • c'est votre déclaration CASE qui fait la comparaison à l'intérieur de l'instruction CASE. Je suppose que si vous placez votre instruction CASE dans votre SELECT, vous obtiendrez un booléen "1" ou "0" indiquant si l'instruction CASE a été évaluée comme étant vraie ou fausse.

6voto

Gont Points 51

J'ai pris votre exemple et je l'ai modifié :

SELECT  *
FROM    sys.indexes i
    JOIN sys.partitions p
        ON i.index_id = p.index_id 
    JOIN sys.allocation_units a
        ON a.container_id = (CASE
           WHEN a.type IN (1, 3)
               THEN p.hobt_id 
           WHEN a.type IN (2)
               THEN p.partition_id
           ELSE NULL
           END)

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