1

SQL 2008/2012 を使用してステータス間の時間枠を計算する

学生のステータスを保存する次のテーブルがあります

+----+-----------+------------------+---------+---------+
| ID | PERSON_ID |    TIMESTAMP     | IN_HOME | STUDYNG |
+----+-----------+------------------+---------+---------+
|  1 |         1 | 17/10/2012 19:00 |       0 |       0 |
|  2 |         1 | 17/10/2012 19:02 |       1 |       0 |
|  3 |         1 | 17/10/2012 19:03 |       1 |       1 |
|  4 |         1 | 17/10/2012 19:04 |       1 |       1 |
|  5 |         1 | 17/10/2012 19:05 |       1 |       0 |
|  6 |         1 | 17/10/2012 19:10 |       0 |       0 |
|  7 |         1 | 17/10/2012 19:12 |       0 |       0 |
|  8 |         1 | 17/10/2012 19:20 |       1 |       0 |
|  9 |         1 | 17/10/2012 19:25 |       1 |       0 |
| 10 |         1 | 17/10/2012 19:26 |       1 |       1 |
| 11 |         1 | 17/10/2012 19:30 |       1 |       0 |
+----+-----------+------------------+---------+---------+

そして、いくつかのレポートを作成するために2つの方法で結果を生成したいと思います:

私:

+-----------+------------------+------------------+---------+---------+
| PERSON_ID |      START       |       END        | IN_HOME | STUDYNG |
+-----------+------------------+------------------+---------+---------+
|         1 | 17/10/2012 19:00 | 17/10/2012 19:02 |       0 |       0 |
|         1 | 17/10/2012 19:02 | 17/10/2012 19:03 |       1 |       0 |
|         1 | 17/10/2012 19:03 | 17/10/2012 19:05 |       1 |       1 |
|         1 | 17/10/2012 19:05 | 17/10/2012 19:10 |       1 |       0 |
|         1 | 17/10/2012 19:10 | 17/10/2012 19:20 |       0 |       0 |
|         1 | 17/10/2012 19:20 | 17/10/2012 19:26 |       1 |       0 |
|         1 | 17/10/2012 19:26 | 17/10/2012 19:30 |       1 |       1 |
+-----------+------------------+------------------+---------+---------+

Ⅱ:

+-----+------------------+------------------+--------+---------+----------+----------+
| PID |      START       |       END        | InHOME | TotTIME | FreeTIME | StudTIME |
+-----+------------------+------------------+--------+---------+----------+----------+
|   1 | 17/10/2012 19:00 | 17/10/2012 19:02 |      0 | 2min    | 2min     | 0min     |
|   1 | 17/10/2012 19:02 | 17/10/2012 19:10 |      1 | 8min    | 6min     | 2min     |
|   1 | 17/10/2012 19:10 | 17/10/2012 19:20 |      0 | 10min   | 10min    | 0min     |
|   1 | 17/10/2012 19:20 | 17/10/2012 19:26 |      1 | 6min    | 6min     | 0min     |
+-----+------------------+------------------+--------+---------+----------+----------+

この問題を解決するための最良の解決策は何ですか?

4

2 に答える 2

0

最初のものはこのように見えるかもしれません。レポート I の最後の行に STUDYING = 0 がある理由がわかりません (間違いかもしれません)。

select
    T.PERSON_ID,
    min(T.[TIMESTAMP]) as START,
    CALC.[TIMESTAMP] as [END],
    T.IN_HOME, T.STUDYNG
from @Temp as T
    cross apply
    (
        select top 1 TT.*
        from @Temp as TT
        where 
            TT.PERSON_ID = T.PERSON_ID and TT.[TIMESTAMP] > T.[TIMESTAMP] and
            (TT.IN_HOME <> T.IN_HOME or TT.STUDYNG <> T.STUDYNG)
        order by TT.[TIMESTAMP] asc
    ) as CALC
group by 
    T.PERSON_ID,
    CALC.[TIMESTAMP],
    T.IN_HOME, T.STUDYNG
order by START
于 2012-10-17T05:59:37.007 に答える
0

SQL 2012 を使用できる場合 (タイトルに記載されているとおり)、LEAD/LAG関数の使用を検討することをお勧めします。

SQL Fiddle がオンラインに戻ったら、ちょっとした素敵な例を作ってみます。

最初の部分は次のとおりです。

;WITH DATA 
     AS (SELECT *, 
                CASE 
                  WHEN ID = 1 THEN 1 
                  ELSE 
                    CASE 
                      WHEN IN_HOME = Lag(IN_HOME, 1) 
                                       OVER ( 
                                         ORDER BY TIMESTAMP) 
                           AND STUDYNG = Lag(STUDYNG, 1) 
                                           OVER ( 
                                             ORDER BY TIMESTAMP) THEN 0 
                      ELSE 1 
                    END 
                END rn 
         FROM   STUDY), 
     PREPARED_DATA 
     AS (SELECT t1.ID, 
                t1.PERSON_ID, 
                t1.TIMESTAMP, 
                Sum(t2.RN) RN, 
                t1.IN_HOME, 
                t1.STUDYNG 
         FROM   DATA t1 
                INNER JOIN DATA t2 
                        ON t1.ID >= t2.ID 
         GROUP  BY t1.ID, 
                   t1.PERSON_ID, 
                   t1.TIMESTAMP, 
                   t1.IN_HOME, 
                   t1.STUDYNG), 
     SECOND 
     AS (SELECT PERSON_ID, 
                Max(TIMESTAMP) max_time, 
                Min(TIMESTAMP) min_time, 
                IN_HOME, 
                STUDYNG 
         FROM   PREPARED_DATA 
         GROUP  BY PERSON_ID, 
                   IN_HOME, 
                   STUDYNG, 
                   RN) 
SELECT PERSON_ID, 
       MAX_TIME, 
       Lead(MIN_TIME, 1) 
         OVER ( 
           ORDER BY MIN_TIME), 
       IN_HOME, 
       STUDYNG 
FROM   SECOND 
ORDER  BY MIN_TIME 

実際の例はここにあります。
もしよろしければ、第二弾もご用意できます。私に知らせて。

于 2012-10-17T08:36:24.873 に答える