2014-01-08 7 views
5

Sagen wir, 100 ist ein Start und 101 ist ein Stop-Ereignis. Diese sollten sich abwechseln, und ich möchte herausfinden, wann sie es nicht tun. Jeder Start sollte ein vorheriges Stop-Ereignis haben. Angesichts dieser Tabelle:MySQL findet Zeilen

ID EVENT_ID 
10 100 // a start event 
11 101 // a stop event 
12 99 // some irrelevant event 
13 100 // .. and so on: 
14 101 
15 100 
16 99 // some irrelevant event 
17 100 // <-- duplicate event: bad 
18 100 // <-- duplicate event: bad again. 
19 101 

Ich habe die DATETIME-Spalte weggelassen.

Wie finden Sie # 15 und # 17, da der Start nicht zweimal hintereinander erfolgen sollte?
Das Ergebnis in Form sein sollte:

EVENT_ID FROM_ID FROM_DATETIME UPTO_ID UPTO_DATETIME 
100  15  2014-01-01 14:00 17  2014-01-01 16:00 

ich mir vorstellen, es könnte wie folgt funktionieren:
- ein subselect nur von DATETIME- Ereignisse 100.101 geordnet sind.
- Gruppe von EVENT_ID Duplikate finden count() mit
..aber ich das bezweifeln die Ergebnisse zusammenbrechen können, als Gruppe die Sortierung, nicht würde ignorieren
..und ich weiß, wie die zwei (oder mehr zu bekommen!) jeweilige DATETIME-Werte.

Ist es möglich, dies in MySQL zu finden? Ich könnte das in PHP erledigen, aber das würde ich lieber vermeiden.

+0

Was alle Zeilen auswählen, die = 100 und wo die nächste Zeile nicht über 101 Wert event_id hat? Es kann getan werden. – Goikiu

+0

@Goikiu Das ist die Frage. Was wäre die Syntax? –

+0

Für die richtige Syntax wir brauchen einige erklärt. 1) die ID ist einzigartig? Können Sie ID dupliziert haben? Wird basierend auf bestellt? – Goikiu

Antwort

3

In meinem Beispiel haben alle Zeilen den gleichen datetime-Wert aus Bequemlichkeit.

DROP TABLE IF EXISTS T; 
CREATE TABLE T 
    (`ID` int auto_increment primary key, `EVENT_ID` int, dt timestamp) 
; 

INSERT INTO T 
    (`ID`, `EVENT_ID`) 
VALUES 
    (10, 100), 
    (11, 101), 
    (12, 99), 
    (13, 100), 
    (14, 101), 
    (15, 100), 
    (16, 99), 
    (17, 100), 
    (18, 100), 
    (19, 101) 
; 

select id, event_id, dt as up_to_dt, prevgood, prevdt as from_dt from 
(
select 
T.* 
, if((@startstop = 100 and event_id = 101) or (@startstop = 101 and event_id = 100), 'good', 'bad') as goodbad 
, @prevgood := if(if((@startstop = 100 and event_id = 101) or (@startstop = 101 and event_id = 100), 'good', 'bad') = 'bad', @prevgood, id) as prevgood 
, @prevdt := if(if((@startstop = 100 and event_id = 101) or (@startstop = 101 and event_id = 100), 'good', 'bad') = 'bad', @prevdt, dt) as prevdt 
, @startstop := event_id 
from 
T, (select @startstop:=101, @prevgood:=0, @prevdt:=0) vars 
where event_id in (100, 101) 
order by id 
) sq 
where goodbad = 'bad'; 

Returns

+----+----------+---------------------+----------+---------------------+ 
| id | event_id | up_to_dt   | prevgood | from_dt    | 
+----+----------+---------------------+----------+---------------------+ 
| 17 |  100 | 2014-01-20 09:12:20 |  15 | 2014-01-20 09:12:20 | 
| 18 |  100 | 2014-01-20 09:12:20 |  15 | 2014-01-20 09:12:20 | 
+----+----------+---------------------+----------+---------------------+ 
+0

Sorry @fancyPants Ich meinte 'ID' als Autoinkrement, machte aber einen Tippfehler bei Rekord 17. Deine Lösung ist interessant, zuerst habe ich diese Syntax gesehen. Ich muss deine Lösung genauer untersuchen, bevor ich die Antwort als endgültig akzeptiere . (ein bisschen beschäftigt atm) –

+2

@BarryStaes War über meine Antwort und sah, dass ich eine Spalte verwiesen, die nicht da war. Beim Kopieren und Einfügen scheint etwas falsch gelaufen zu sein. Es ist jetzt korrigiert und ich habe die Spalte auto_increment entfernt, die ich zuvor hinzugefügt habe. Und ich habe Ihre Beispieldaten angepasst (Korrektur des Tippfehlers bei Datensatz 17). Alles sollte jetzt gut sein. – fancyPants