2013-01-11 8 views
5

Mam tabelę podobną do poniższej w MS SQL Server.Min i maks. ID w stosunku do grupy i innego warunku

 id | Timestamp | active 
    -----+-----------+-------- 
     1 | 1:00 | 1 
     1 | 2:00 | 1 
     1 | 3:00 | 1 
     1 | 4:00 | 0 
     1 | 5:00 | 0 
     1 | 6:00 | 1 
     1 | 7:00 | 0 
     1 | 8:00 | 0 
     1 | 9:00 | 0 
     1 | 10:00 | 1 
     1 | 11:00 | 1 
     1 | 12:00 | 0 
     1 | 13:00 | 1 
     2 | 2:00 | 1 
     2 | 3:00 | 1 
     2 | 4:00 | 0 
     2 | 5:00 | 0 
     3 | 8:00 | 0 
     3 | 9:00 | 0 
     4 | 1:00 | 1 
     4 | 2:00 | 1 
     5 | 16:00 | 0 

Co chcę zrobić, dowiedzieć się, kiedy każdy identyfikator był nieaktywny (aktywny = 0) na jak długo. To, co próbowałem zrobić, to pogrupować według id, gdy active = 0, i zrobić notację w czasie min. I maks. Ale to dałoby mi wynik dla id 1, który powiedział, że był offline przez 8 godzin (12:00 - 4:00) @ 12:00. Kiedy naprawdę chcę, to zapytanie, które da mi następujący zestaw wyników.

id | approx. offline in hours | at time 
    ---+--------------------------+----------- 
    1 |   1    | 5:00 
    1 |   2    | 9:00 
    1 |   0    | 12:00 
    2 |   1    | 5:00 
    3 |   0    | 9:00 
    5 |   0    | 16:00 

niewłaściwy zapytanie początkowo próbował to

SELECT id as [Inactive], 
     DATEDIFF(hour, MIN(Timestamp), MAX(Timestamp)) as [approx. offline in hours], 
     MAX(Timestamp) as [at time] 
FROM table 
WHERE active = 0 
GROUP BY [Inactive] 

Ale problem z tym zapytania jest to, że pomija Całość razy pomiędzy. Patrzę na pytanie, które zostało zadane i odebrane za pomocą PARTYCJI, ale wygląda na to, że pytanie jest wystarczająco różne, a odpowiedź jest zbyt specyficzna dla pytania, które nie jest w stanie nadać mu sensu.

Każda pomoc jest doceniana.

+0

jakiego rdbms używasz? sql-server, oracle? – Taryn

+0

@bluefeet Kwadratowe nawiasy najprawdopodobniej == SQL Server –

+0

@JoachimIsaksson Zgadzam się, ale powinny one określać, jakich używają one rdbms. – Taryn

Odpowiedz

3

Jednym ze sposobów podejścia, który działa w dowolnej bazie danych, jest użycie skorelowanego podzapytania. Chodzi o to, aby przypisać nazwę grupy do każdego kolejnego ciągu aktywnych wartości. Szczególna nazwa grupy to czas następnej zmiany wartości.

select id, active, min(TimeStamp), max(TimeStamp) 
from (select t.*, 
      (select min(timeStamp) from t t2 where t2.id = t.id and t2.timeStamp > t.timeStamp and t2.active <> t.active 
      ) groupName 
     from t 
    ) t 
group by id, groupName, active 

Jeden z zastrzeżeń, w jaki sposób przekształcić znaczniki czasu w czasy trwania, zależy od bazy danych. Ponieważ nie określasz bazy danych, pozwolę ci dodać tę logikę.

Ponadto, jeśli ostatni rekord dla danego id jest nieaktywny, nazwa grupy ma wartość NULL. To nie jest problem.

+0

Myślę, że w tej odpowiedzi jest błąd, ponieważ groupName będzie NULL, gdy ID zmieni się – Bulat

+0

@Bulat. . . To nie jest problem. Wartość NULL jest poprawna dla grupowania, a identyfikator jest zawarty w kolumnach 'group by'. –

+0

Tak, masz rację, to nie jest problem. Możesz po prostu zmienić nazwę TimesStamp na czas, aby nazwy pól były spójne. http://sqlfiddle.com/#!3/e5831/45/0 – Bulat

Powiązane problemy