Vous n'êtes pas identifié(e).

#1 26/10/2011 12:10:05

moromain
Membre

Recherche du premier et du deuxième d'une liste

Bonjour,
Débutant avec postgresql, je n'arrive pas à obtenir le premier enregistrement d'une liste.
Champ1 |  Champ2
     a      |       9
     a      |       5
     a      |       2
     b      |     12
     b      |     52
     b      |       3

J'aimerai réduire cette liste aux premiers "champ2" pour chaque "champ1", soit :
Champ1 |  Champ2
     a      |       9
     b      |     12

Ce ne sont pas des max à chaque fois.
J'ai essayé avec First, mais je ne comprends pas la syntaxe dans le select.
En bonus, si je peux obtenir le 2e (en plus du premier) :
Champ1 |  Champ2
     a      |       9
     a      |       5
     b      |     12
     b      |     52
Merci d'avance !

Hors ligne

#2 26/10/2011 12:15:34

rjuju
Administrateur

Re : Recherche du premier et du deuxième d'une liste

Bonjour,
si vous êtes en Postgresql 9.0 ou supérieur, vous pouvez le faire facilement avec les fonctions window

Pour votre exemple :

SELECT DISTINCT "Champ1",min("Champ2") OVER (PARTITION BY "Champ1")
FROM table

Pour avoir les 2 premières  valeurs de chaque Champ1, il faut imbriquer une requête :

SELECT "Champ1","Champ2" FROM (
  SELECT "Champ1","Champ2", row_number() OVER (PARTITION BY "Champ1" ORDER BY "Champ2") as rang
  FROM table
) sql
WHERE rang < 3

Edit : Oups, j'ai lu trop vite. Pour renvoyer la première valeur ou les 2 premières valeurs, il est necessaire d'avoir un champ supplémentaire (créer la table avec un oid ou avec un serial), sinon la requête ne pourra pas ramener forcément les même enregistrements, les données n'ayant pas réellement d'ordre. Il faut donc ensuite adapter les fonctions window avec le min ou le order sur le champ serial ou oid.

Dernière modification par rjuju (26/10/2011 12:30:33)

Hors ligne

#3 26/10/2011 16:53:56

moromain
Membre

Re : Recherche du premier et du deuxième d'une liste

Je travaille avec une version 8.3 sur un serveur, et pas moyen de la mettre à jour dans l'immédiat.

C'est une requête qui va me retourner les valeurs. Si ça avait été une table, un serial par exemple aurait fait l'affaire.
Y a t'il un moyen de créer un champ "C4" qui recevrait une incrémentation de +1 à chaque ligne, dans le sens décroissant de C3 ?

C1   |C2|C3  |C4
1591| 7 | 30 | 1
1591| 7 | 27 | 2
1591| 7 | 26 | 3
1591| 6 | 24 | 4
1591| 6 | 23 | 5
1591| 2 |  6  | 6
1591| 1 |  4  | 7
1591| 1 |  1  | 8

Ainsi, pour chaque C1, je récupère les "1" et "2" de C4.

Hors ligne

#4 26/10/2011 18:48:58

rjuju
Administrateur

Re : Recherche du premier et du deuxième d'une liste

Pour être sur du résultat, il faut également que votre requête source utilise un order by.

Il est possible de faire ça avec un auto-join, mais les performances risquent d'être catastrophique sur une grosse table.

Grosso modo, ça serait une requête de ce genre :

SELECT c2,c3 FROM (
  SELECT t1.c2,t1.c3, COUNT(*) as rang
  FROM table t1, table t2
  WHERE t1.[CHAMP TRI] >= t2.[CHAMP TRI]
  GROUP BY t1.c2,t1.c3
  ORDER BY rang
) sql
WHERE rang <3

Hors ligne

Pied de page des forums