Bonsoir,


Disons que j'ai une table
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
 
CREATE TABLE MaTable (
   id BIGINT,
   sender INT,
   value SMALLINT
);
Pour chaque sender, je souhaite extraire toutes les lignes ayant le champ valeur différente de la valeur précédente (id est une clé primaire servant aussi pour l'ordre chronologique sur cet exemple)

J'ai une technique via une table intermédiaire et un trigger à l'insertion me permettant de récupérer au fur et à mesure ce résultat... mais je veux aussi avoir une vraie requête performante pour effectuer cette tâche.


Actuellement, en SQL "simple", j'aurais ceci :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 
SELECT m.Id as "id",m.sender as "sender" FROM MaTable m
   WHERE NOT EXISTS (
      SELECT m_.Id FROM MaTable m_
         WHERE m_.Id<m.Id AND m_.sender=m.sender
      )
UNION
SELECT m1.Id as "id", m1.sender as "sender" 
   FROM MaTable m1, MaTable m2
   WHERE 
      m1.sender=m2.sender AND m1.value!=m2.value AND m1.Id>m2.Id
      AND NOT EXISTS (
         SELECT m_.Id FROM main m_ 
            WHERE 
               m2.value!=m_.value AND m_.sender=m1.sender
               AND m_.Id>m2.Id AND m_.Id<m1.Id 
      )
ORDER BY sender,id
Disons que ce n'est clairement pas optimal... je reste donc à la solution du trigger à l'insertion. J'ai également une méthode passant par une table intermédiaire et effectuant un seq scan de MaTable. Rien de très sympa


Du coup, en performant, je peux lancer ceci à base de fenêtrage
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
 
SELECT id,sender,value,
   rank() OVER (PARTITION BY sender ORDER BY id) as "rg"
   from MaTable
;
Je tente ceci
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
 
select tbl.*
 , nth_value(value,rg-1) over w as "prec"
from (
	select m.id,m.sender,m.value,
	rank() over w as "rg"
	from MaTable m
	window w as (partition by m.sender order by m.id)
) as tbl
;
Mais je ne vois pas trop comment






EDIT: une astuce
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
WITH tbl AS (
   SELECT m.id,m.sender,me.value,
      rank() OVER (
         PARTITION BY m.sender
         ORDER BY m.id
   ) AS "rg", 
   sum(value) OVER (
      PARTITION BY m.sender 
      ORDER BY m.id ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING
   ) as "prec"
   FROM MaTable m
)
SELECT tbl.id FROM tbl WHERE tbl.immo!=tbl.prec
des conseils pour optimiser cela ?