Equivalent de plusieurs COUNT(x WHERE y = z) dans une requête ? - SQL/NoSQL - Programmation
Marsh Posté le 08-02-2006 à 10:03:38
Bonjour,
Je ne sais pas si ton SGBD accepte cette syntaxe ?
select distinct(IDCLIENT),
IIF(statut = 'statut1', count(statut), 0) as 'stat1',
IIF(statut = 'statut2', count(statut), 0) as 'stat2',
etc ...
Marsh Posté le 08-02-2006 à 10:54:38
Tout d'abord, merci pour ta réponse.
Il s'agit d'une base SqlServer 2000, du coup j'ai traduit le IIF par un CASE, ce qui me donne ça:
SELECT
DISTINCT IDclient,
(CASE
WHEN statut ='statut1'
THEN count(statut)
ELSE 0
END) AS stat1,
(CASE
WHEN statut = 'statut2'
THEN count(statut)
ELSE 0
END) AS stat2,
(CASE
WHEN statut = 'statut3'
THEN count(statut)
ELSE 0
END) AS stat3
FROM maTable
WHERE pleinDeConditions
GROUP BY IDclient,statut
Le problème est que ça me renvoie une ligne par couple {IDclient,statut} or je n'en voudrais qu'une !
C'est-à-dire au lieu de ça:
IDclient stat1 stat2 stat3
99999 0 0 1
99999 1 0 0
je voudrais ça:
IDclient stat1 stat2 stat3
99999 1 0 1
Est-ce que c'est possible ???
Merci d'avance
Marsh Posté le 08-02-2006 à 11:09:59
Re,
Désolé, je ne connais pas SqlServer. C'était juste pour l'idée.
Bonne chance.
Marsh Posté le 08-02-2006 à 13:11:49
Bon, en fait j'ai trouvé alors si ça peut intéresser quelqu'un voilà comment j'ai fait (c'est peut-être pas ce qu'il y a de mieux, mais c'est toujours beaucoup plus performant que la première solution que j'avais à base de fonctions... désolée, je débute...)
Le but de ma requête est de construire un tableau avec les colonnes suivantes :
IDClient,TotalDossiersOK,TotalDossiersKO,TotalDossiersEnCours
Je suis passée par une derived table récupérant mes IDClient,le total de dossiers OK, le total de dossiers KO, le total de dossiers EC :
SELECT
DISTINCT IDClient,
(CASE WHEN statut='OK' THEN COUNT(statut) ELSE 0 END) AS OK,
(CASE WHEN statut LIKE 'KO' THEN COUNT(statut) ELSE 0 END) AS KO,
(CASE WHEN statut = 'EC' THEN COUNT(statut) ELSE 0 END) AS EC
FROM maTable
WHERE mesConditions
GROUP BY IDClient, statut
Ce qui me renvoie une ligne par IDClient et par statut différent trouvé.
Par exemple :
IDClient OK KO EC
99999 0 8 0
99999 1 0 0
Ensuite il suffit juste de faire des sommes...
SELECT
DISTINCT IDClient,
SUM(OK) AS TotalOK,
SUM(KO) AS TotalKO,
SUM(EC) AS TotalEC
FROM
(SELECT
DISTINCT IDClient,
(CASE WHEN statut='OK' THEN COUNT(statut) ELSE 0 END) AS OK,
(CASE WHEN statut LIKE 'KO' THEN COUNT(statut) ELSE 0 END) AS KO,
(CASE WHEN statut = 'EC' THEN COUNT(statut) ELSE 0 END) AS EC
FROM maTable
WHERE mesConditions
GROUP BY IDClient, statut) AS MaSousTable
GROUP BY IDClient
ORDER BY IDClient
Et j'obtiens
IDClient OK KO EC
99999 1 8 0
Merci beaucoup pc75 de m'avoir mise sur la voie...
Marsh Posté le 08-02-2006 à 09:45:10
Bonjour,
J'ai une table avec entre autres les champs suivants IDClient (Int) et statut (NVarChar)
Et je souhaiterais faire une requête de ce style-là :
SELECT
DISTINCT(IDClient),
COUNT(statut WHERE statut='statut1'),
COUNT(statut WHERE statut='statut2'),
COUNT(statut WHERE statut='statut3')
FROM maTable
WHERE mesConditions
GROUP BY IDClient
C'est-à-dire obtenir un tableau avec 4 colonnes : 1/ IDClient, 2/ le nombre de fois où IDClient apparaît avec le statut 'statut1', 3/ le nombre de fois où IDClient apparaît avec le statut 'statut2', 4/ le nombre de fois où IDClient apparaît avec le statut 'statut3'
Ca ne me paraît pas la mort comme besoin, mais je n'arrive pas à trouver comment faire "élégamment" avec des temps d'exécution raisonnable sur une grosse table...
Le mieux que j'ai trouvé, c'est avec des fonctions, ce qui donnait quelque chose comme ça:
SELECT
DISTINCT(IDClient),
compterStatuts('statut1',IDClient,ceQuilFautPourMesConditions),
compterStatuts('statut2',IDClient,ceQuilFautPourMesConditions),
compterStatuts('statut3',IDClient,ceQuilFautPourMesConditions)
FROM maTable
WHERE mesConditions
GROUP BY IDClient
Mais ça ne marche bien que quand il n'y a pas trop de champs dans ma table : dès que je passe à une grosse-grosse table, c'est beaucoup trop lent.
Est-ce que quelqu'un pourrait m'aider ?
Merci d'avance