sql >> Databasteknik >  >> RDS >> PostgreSQL

Upptäck SQL-ö över flera parametrar och villkor

Svar på uppdaterad fråga

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)

Hur?

Samma som tidigare, men denna gång kombinera två fönsterfunktioner. Att slå på en enhet kvalificerar sig om ..
1. den senaste enheten som slogs på var annan en.
2. eller samma enhet har stängts av av i sin sista post. Hörnfallet med NULL för den första raden i partitionen är irrelevant, eftersom raden då redan kvalificerade sig i 1.

Svar på originalversionen av frågan.

Om din Jag förstår din uppgift rätt, gör denna enkla fråga jobbet:

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

Returnerar raderna 1, 3, 6, 7 efter önskemål.

Hur?

Underfrågan ignorerar all avstängning, eftersom det bara är brus, enligt din beskrivning. Lämnar poster där en enhet är påslagen. Bland dessa är endast de poster diskvalificerade, där samma enhet redan var på (den senaste posten slås på). Använd fönsterfunktionen lag() för det. Jag tillhandahåller särskilt 0 som standard för att täcka specialfallet för den första raden - förutsatt att det inte finns någon enhet med val = 0 .
Om det finns, välj ett annat omöjligt nummer.
Om inget nummer är omöjligt, lämna specialfallet som NULL med lag(val) OVER ... och i den yttre frågan kontrollera med:

WHERE last_on IS DISTINCT FROM val



  1. PostgreSQL FÖRKLARA – Vilka är frågekostnaderna?

  2. Hur skapar man ett unikt slumpmässigt heltals-ID för primärnyckel för tabell?

  3. Att använda Solr sökindex som en databas - är det fel?

  4. Databastrender 2019 – SQL vs. NoSQL, bästa databaser, enstaka vs. flera databasanvändning