Select count distinct multiple columns avec group by

La norme SQL évolue : tirez le meilleur d'un SGBD qui la respecte en écrivant du SQL moderne avec en complément PL/pgSQL, php, java etc.
Répondre
Phil
Administrateur du site
Messages : 184
Enregistré le : mar. 1 sept. 2015 00:38
Localisation : France
Contact :

Select count distinct multiple columns avec group by

Message par Phil » lun. 11 déc. 2017 17:44

Merci à Jean-Luc pour sa question :

Nous avons une petite question de syntaxe en sql.
Y a-t-il un moyen simple de faire un count(*) sur un distinct de deux colonnes ?

Par exemple, dans la requête suivante, nous devons remplacer le distinct (c3) par un distinct sur le couple c3/c4
select c1, c2, count(distinct c3)
from t1
group by c1, c2 ;

Je pensais à la méthode suivante en utilisant l’opérateur || mais je ne suis pas sûr que ce soit très académique.
select c1, c2, count(distinct c3 || c4)
from t1
group by c1, c2;

Y a-t-il une syntaxe plus adaptée ?

En vous remerciant par avance.


Réponse :
C'est vrai qu'une recherche Internet avec select count distinct 2 multiple columns group by etc. ne donne pas forcément de réponse très claire.
La requête envisagée est syntaxiquement correcte si au moins une des colonnes c3 ou c4 est de type text mais pas sûr que ce soit fonctionnellement correct.
Est-ce que le "couple" (11,1) doit être considéré comme distinct de (1,11) par exemple ? Si ces 2 couples doivent être considérés comme distincts alors la requête peut retourner des résultats faux. Il serait possible d'utiliser un séparateur pour limiter les risques et d'écrire par exemple select c1, c2, count(distinct c3 || '<->' || c4)
Mais, en fonction de la nature des données, ce n'est toujours pas une réponse sûre à 100%.
Une idée avec PostgreSQL peut être d'utiliser les constructeurs de lignes (row constructors).
Exemple :

Code : Tout sélectionner

select version();
                                                 version
---------------------------------------------------------------------------------------------------------
 PostgreSQL 10.3 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-16), 64-bit
(1 ligne)

create table t1(c1 int, c2 int, c3 int, c4 int);
CREATE TABLE

insert into t1(c1, c2, c3, c4) values
(1,1,11,1),
(1,1,11,1),
(1,1,1,11),
(1,1,null,111),
(1,1,2,2),
(1,1,2,null),
(1,1,null,null),
(1,2,11,1),
(1,2,1,11),
(1,2,11,1),
(1,2,null,111),
(1,3,2,2),
(1,4,2,null),
(1,4,null,null),
(2,null,null,null),
(2,null,null,null),
(null, null, null, null),
(null, null, null, null)
;
INSERT 0 18

select c1, c2, count(distinct(row(c3, c4))) 
from t1
group by c1, c2
;
  c1  |  c2  | count
------+------+-------
    1 |    1 |     6
    1 |    2 |     3
    1 |    3 |     1
    1 |    4 |     2
    2 |      |     1
      |      |     1
(6 lignes)

-- row peut etre omis dans ce cas
select c1, c2, count(distinct(c3, c4)) 
from t1
group by c1, c2
;

  c1  |  c2  | count
------+------+-------
    1 |    1 |     6
    1 |    2 |     3
    1 |    3 |     1
    1 |    4 |     2
    2 |      |     1
      |      |     1
(6 lignes)

Cdlt. Phil - pgphil.ovh

Répondre