Μια εναλλακτική λύση που βασίζεται σε TSQL query. Πάμε βήμα-βήμα:
Ας υποθέσουμε ότι ο πίνακάς μας είναι ο παρακάτω:
table switch(Con int, Dt DateTime)
και τα περιεχόμενα είναι αυτά που περιγράφονται στο πρώτο post. Αυτό που μπορούμε να κάνουμε είναι να θεωρήσουμε ότι έχουμε δύο πίνακες, τον s0 που έχει όλα τα OFF και τον s1 που έχει όλα τα ON.
Ας εκτελέσουμε τα παρακάτω:
SELECT *
FROM switch
WHERE con = 0
SELECT *
FROM switch
WHERE con = 1
Παρατηρούμε ότι τα αποτελέσματα είναι τα παρακάτω:
Con Dt
----------- -----------------------
0 2007-05-28 10:22:34.000
0 2007-05-28 13:25:30.000
0 2007-05-28 18:33:01.000
(3 row(s) affected)
Con Dt
----------- -----------------------
1 2007-05-28 11:35:04.000
1 2007-05-28 17:45:56.000
1 2007-05-28 23:29:34.000
(3 row(s) affected)
Μπορούμε να κάνουμε join τους δύο πίνακες κάπως έτσι:
SELECT s0.*, s1.* FROM
(SELECT * FROM switch
WHERE con=0) s0 INNER JOIN (
SELECT * FROM switch
WHERE con=1) s1 ON s0.dt<s1.dt
Το πρόβλημα όπως φαίνεται είναι ότι στο ON clause δεν μπορούμε να έχουμε τελεστή ισότητας καθώς δεν υπάρχουν κοινά πεδία, ωστόσο τίποτα δεν μας εμποδίζει να χρησιμοποιήσουμε τους τελεστές όπως φαίνεται παραπάνω. Το αποτέλεσμα που μας δίνει αυτό το query είναι:
Con Dt Con Dt
----------- ----------------------- ----------- -----------------------
0 2007-05-28 10:22:34.000 1 2007-05-28 11:35:04.000
0 2007-05-28 10:22:34.000 1 2007-05-28 17:45:56.000
0 2007-05-28 13:25:30.000 1 2007-05-28 17:45:56.000
0 2007-05-28 10:22:34.000 1 2007-05-28 23:29:34.000
0 2007-05-28 13:25:30.000 1 2007-05-28 23:29:34.000
0 2007-05-28 18:33:01.000 1 2007-05-28 23:29:34.000
Άρα αυτό που έχουμε πετύχει προς το παρόν είναι να βάλουμε σε μία γραμμή μαζί τις τιμές έναρξης και λήξης ώστε να μπορέσουμε στη συνέχεια να κάνουμε υπολογισμούς. Αυτό που μένει είναι να ξεφορτωθούμε τις γραμμές που δεν μας κάνουν. Για παράδειγμα, η έναρξη στις 10:22 εμφανίζεται με λήξη στις 11:35, 17:45 και 23:29. Εμείς θέλουμε να κρατήσουμε την εγγύτερη τιμή, αυτήν που εμφανίστηκε πρώτη, δηλαδή την ελάχιστη από τις τρεις. Θα πρέπει λοιπόν να βάλουμε ένα min aggregation πάνω στο πεδίο της λήξης, που σημαίνει ότι πρέπει τα υπόλοιπα πεδία να μπουν σε group by. Έτσι, τελικά το query μας γίνεται κάπως έτσι:
SELECT s0.dt start, MIN(s1.dt) finish, DATEDIFF(ss,s0.dt,MIN(s1.dt)) secs FROM
(SELECT * FROM switch
WHERE con=0) s0 INNER JOIN (
SELECT * FROM switch
WHERE con=1) s1 ON s0.dt<s1.dt
GROUP BY s0.dt
Που μας δίνει τα παρακάτω αποτελέσματα:
start finish secs
----------------------- ----------------------- -----------
2007-05-28 10:22:34.000 2007-05-28 11:35:04.000 4350
2007-05-28 13:25:30.000 2007-05-28 17:45:56.000 15626
2007-05-28 18:33:01.000 2007-05-28 23:29:34.000 17793
Vir prudens non contra ventum mingit