Obtention de lignes distinctes sur une requête SQL avec plusieurs colonnes IIF

Dans SQL Server, je crée une vue qui montre si un logging dans la table CONTACTS a certaines balises dans une table différente TAGS.

C'est ma requête:

SELECT DISTINCT contacts.ID, contacts.NAME, IIF(tags.tag = 'A', 1, 0) as A, IIF(tags.tag = 'B', 1, 0) as B, IIF(tags.tag = 'C', 1, 0) as C, IIF(tags.tag = 'D', 1, 0) as D FROM contacts LEFT JOIN TAGS ON contacts.ID = TAGS.CONTACT_ID 

Je voudrais les résultats comme ceci:

 ID NAME ABCD ------------------------------------ 1 BOB 1 0 0 1 1 Charlie 1 0 1 0 

mais je reçois

 ID NAME ABCD ------------------------------------ 1 BOB 1 0 0 0 1 BOB 0 0 0 1 1 Charlie 1 0 0 0 1 Charlie 0 0 1 0 

Doit être quelque chose que je néglige, mais je ne peux pas le find.

Utilisez le group by :

 SELECT c.ID, c.NAME, MAX(CASE WHEN t.tag = 'A' THEN 1 ELSE 0 END) as A, MAX(CASE WHEN t.tag = 'B' THEN 1 ELSE 0 END) as B, MAX(CASE WHEN t.tag = 'C' THEN 1 ELSE 0 END) as C, MAX(CASE WHEN t.tag = 'D' THEN 1 ELSE 0 END) as D FROM contacts c LEFT JOIN TAGS t ON c.ID = t.CONTACT_ID GROUP BY c.ID, c.NAME; 

Remarque modifie la requête:

  • Alias ​​de table introduits. Ceux-ci rendent la requête plus facile à écrire et à lire.
  • Suppression du SELECT DISTINCT , car vous voulez vraiment un GROUP BY .
  • Changé IIF() à CASE . Je ne vois aucune raison d'utiliser une fonction conçue pour la rétrocompatibilité avec MS Access par rapport à la fonction standard SQL.

Vous devez simplement utiliser la clause GROUP BY + MAX aggreate au lieu de DISTINCT

 SELECT contacts.ID, contacts.NAME , MAX(IIF(tags.tag = 'A', 1, 0)) as A , MAX(IIF(tags.tag = 'B', 1, 0)) as B , MAX(IIF(tags.tag = 'C', 1, 0)) as C , MAX(IIF(tags.tag = 'D', 1, 0)) as D FROM contacts LEFT JOIN TAGS ON contacts.ID = TAGS.CONTACT_ID group by contacts.ID, contacts.NAME 

Comme le dit Gordon Linoff, l'utilisation du case when SQL standard est plus compatible avec toute la database (postgres, oracle, sql server …)

 IIF(tags.tag = 'A', 1, 0) 

est équivalent à

 CASE WHEN tags.tag = 'A' THEN 1 ELSE 0 END 
 SELECT contacts.ID, contacts.NAME , MAX(IIF(tags.tag = 'A', 1, 0)) as A , MAX(IIF(tags.tag = 'B', 1, 0)) as B , MAX(IIF(tags.tag = 'C', 1, 0)) as C , MAX(IIF(tags.tag = 'D', 1, 0) as D FROM contacts LEFT JOIN TAGS ON contacts.ID = TAGS.CONTACT_ID GROUP BY contacts.ID, contacts.NAME