Détection de changement de valeurs sur un champ
Bonsoir,
Disons que j'ai une table
Code:
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:
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 :aie:
Du coup, en performant, je peux lancer ceci à base de fenêtrage
Code:
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:
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 :?
:merci:
EDIT: une astuce
Code:
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 ?