PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Détecter l'îlot SQL sur plusieurs paramètres et conditions

Réponse à la question mise à jour

SELECT *
FROM  (
   SELECT *
         ,lag(val, 1, 0) OVER (PARTITION BY status ORDER BY id) last_val
         ,lag(status) OVER (PARTITION BY val ORDER BY id) last_status
   FROM   t1
   ) x
WHERE  status = 1
AND    (last_val <> val OR last_status = 0)

Comment ?

Comme avant, mais cette fois combinez deux fonctions de fenêtre. La mise en marche d'un appareil est admissible si ..
1. le dernier appareil allumé était un différent un.
2. ou le même appareil a été éteint dans sa dernière entrée. Le cas du coin avec NULL pour la première ligne de la partition n'est pas pertinente, car alors la ligne est déjà qualifiée dans 1.

Réponse pour la version originale de la question.

Si vous avez bien compris votre tâche, cette simple requête fait l'affaire :

SELECT *
FROM  (
   SELECT *
         ,lag(val, 1, 0) OVER (ORDER BY id) last_on
   FROM   t1
   WHERE  status = 1
   ) x
WHERE  last_on <> val

Renvoie les lignes 1, 3, 6, 7 comme demandé.

Comment ?

La sous-requête ignore toute mise hors tension, car ce n'est que du bruit, selon votre description. Laisse des entrées là où un appareil est allumé. Parmi ceux-ci, seules les entrées sont disqualifiées, où le même appareil était déjà allumé (la dernière entrée s'allumant). Utilisez la fonction de fenêtre lag() pour ça. En particulier, je fournis 0 par défaut pour couvrir le cas particulier de la première ligne - en supposant qu'il n'y a pas de périphérique avec val = 0 .
S'il y en a un, choisissez un autre nombre impossible.
Si aucun nombre n'est impossible, laissez le cas particulier NULL avec lag(val) OVER ... et dans la requête externe, vérifiez avec :

WHERE last_on IS DISTINCT FROM val