Count distinct sur plusieurs champs a la fois [SGBD/SQL] - SQL/NoSQL - Programmation
Marsh Posté le 01-08-2014 à 06:35:38
Je suis tombé sur ce lien : http://stackoverflow.com/questions [...] le-columns
Avec des solutions toutes aussi moches les unes que les autres . C'est quel SGBD au fait ?
Marsh Posté le 01-08-2014 à 09:18:28
ReplyMarsh Posté le 01-08-2014 à 15:47:36
Yonel a écrit : Je suis tombé sur ce lien : http://stackoverflow.com/questions [...] le-columns |
Oracle.
Malheureusement ton lien ne fait pas la meme chose - le gars cherche a compter les paires distinctes, et non pas les valeurs uniques presentes dans deux colonnes differentes a la fois.
ddr555 a écrit : quelle est la raison pour laquelle tu ne veux pas de sous requête ? |
En gros, c'est dans une procedure stockee, et il y a une requete du genre (en tres tres simplifie):
SELECT <champs divers> |
La condition dans le where est "parametrable": la requete est declaree comme VARCHAR2, et [condition] est remplace dynamiquement par une autre chaine de caractere stockee en base, et apres remplacement, le code fait un EXECUTE IMMEDIATE.
Il y a deja une condition (relativement simple) en place et on m'a demande de voir si c'etait possible d'y ajouter facilement un certain nombre de criteres. Si je peux le faire en modifiant la condition, je m'en sors avec un UPDATE sur un champ en base et c'est "facile". Si je peux pas et que je dois reecrire la procedure stockee ou autre, ca devient super casse couilles a cause des process de ma boite: oblige de tout documenter, tester, faire valider, etc.
Maintenant le probleme c'est que un des criteres a besoin de faire ce COUNT de mon premier post, pour avoir un truc dans le genre:
SELECT <champs divers> |
Sauf que le <parametre> est en fait un des champs de la requete initiale, accede sous la forme alias.champ.
Et ce genre d'access ne marche que si la reference est faite au "premier niveau" dans la sous-requete.
Bon il y a p'tetre une astuce que je ne connais pas pour pouvoir y acceder dans les sous-niveaux.
J'ai reussi a avoir un truc qui marche, toujours avec une sous-requete mais en deplacant la comparaison avec champ3 au "premier" niveau, mais bon niveau perf c'est une horreur pour le moment. Je vais quand meme essayer de bidouiller quelques hints pour voir.
Marsh Posté le 01-08-2014 à 15:53:28
SELECT COUNT(*)
FROM (
SELECT champ1 c1,champ3
FROM table
UNION
SELECT champ2 c1,champ3
FROM table
)
WHERE champ3 = <parametre>
ne marche pas bien ?
tu peux pas créer une vue matérialisée que tu rafraichirais au début du traitement contenant les données ?
Marsh Posté le 01-08-2014 à 16:18:35
ddr555 a écrit : SELECT COUNT(*) ne marche pas bien ? |
Si, c'est a peu pres la ou j'en suis, mais pour l'instant, Oracle decide qu'il doit completement executer la sous-requete en premier, et seulement ensuite filtrer sur champ3. Evidemment les sous-requetes contiennent en realite elles-memes plusieurs JOINs ce qui n'aide pas. Une des tables impliquees etant relativement grosse, ca va pas aller. (Edit: pour le moment, l'explain plan prevoit 42 heures d'execution)
ddr555 a écrit : tu peux pas créer une vue matérialisée que tu rafraichirais au début du traitement contenant les données ? |
Si mais meme probleme que modification de la procedure stockee: tout ce qui sort d'un strict update du champ en base contenant la condition va rajouter du boulot (re-spec, tests, go/no go etc.).
Si ca finit comme ca, vu que le resultat du COUNT est en realite fixe pour chaque champ3, je pense plutot ajouter un champ quelque part pour le calculer une seule fois, stocker le resultat pour toujours et basta.
Marsh Posté le 01-08-2014 à 16:35:07
si ça ne varie pas, autant faire ça par un create table as select champ3,count(*) ... group by champ 3 et tu n'as plus qu'à faire un select dans ta table créée. d'où la vue matérialisée si le résultat avait du changer au cours du temps
Marsh Posté le 31-07-2014 à 20:23:33
Salut
J'ai une requete qui me les brise, et je trouve pas de solution.
En gros, est-ce qu'il existe une alternative a ca:
SELECT COUNT(*)
FROM (
SELECT champ1
FROM table
WHERE champ3 = <parametre>
UNION
SELECT champ2
FROM table
WHERE champ3 = <parametre>
)
Mais en evitant l'utilisation de sous-requetes.
Autrement dit, compter toutes les valeurs uniques, mais pas seulement dans une colonne mais deux, et avec une requete de niveau "unique".
Evidemment il faut considerer qu'une meme valeur peut se trouver a la fois dans le champ 1 et le champ 2, sinon c'est facile.
Et pour precision, le parametre est le meme aux deux endroits de la requete.
Pas trouve pour le moment. Si je trouve, ca m'evite de devoir reecrire un gros paquet de trucs.
---------------
C'était vraiment très intéressant.