web-dev-qa-db-ja.com

現在のレコードを以前のレコードと比較する方法

グループ化して、テーブルから読み取るときに現在のレコードを以前のレコードと比較する方法はありますか?私のテーブルは以下のようなものです。

ID    PASSED    LEVEL    CREATEDATE
100   1         2        2016-01-10 07:35:02.123
100   1         2        2016-01-10 07:05:33.135
100   0         2        2016-01-09 08:35:29.123
100   1         2        2016-01-08 09:35:30.123
100   1         1        2016-01-07 11:35:31.123
101   1         1        2016-01-10 08:45:12.123
102   1         1        2016-01-10 09:45:22.222
102   1         1        2016-01-09 08:15:29.123
103   0         1        2016-01-10 07:35:02.123
103   1         2        2016-01-09 06:35:29.023

理想的には、テーブル内のIDごとにBIT値を返す必要があります。

BIT値の条件は、PASSEDが1で、LEVELSがCREATEDATE DESCの順序によって異なる場合に、IDごとに1を返すことです。

したがって、私の例の表では、BIT値

  • 最初と4番目のレコードでPASSEDが1であるため、ID 100は1を返します(レベルは4番目のレコードで変化します)。
  • ID 101は、値1の1つのPASSEDレコードしかないため、BIT値0を返します。
  • 両方のレコードでPASSEDが1であっても、LEVELは両方のレコードで同じであるため、ID 102はBIT値0を返します。
  • LEVELが異なっていても両方のレコードがPASSしなかったため、ID 103は0を返します。

クエリが次のような応答になるようにクエリを構成できることを願っています。

ID    STATUS_PASSED
100   1
101   0
102   0
103   0

提供された助けをありがとう。

4
obautista

これはリレーショナル分割の問題のように思えました。

_DECLARE @results TABLE ( ID INT NOT NULL, PASSED BIT NOT NULL, LEVEL INT NOT NULL, CREATEDATE DATE NOT NULL, PRIMARY KEY ( ID, LEVEL, PASSED, CREATEDATE ) )
DECLARE @levels TABLE ( LEVEL INT PRIMARY KEY )

INSERT INTO @levels
VALUES ( 1 ), ( 2 ) --, ( 3 )    
INSERT INTO @results
VALUES
    ( 100, 1, 2, '1 Oct 2016' ),
    ( 100, 0, 2, '1 Sep 2016' ),
    ( 100, 1, 2, '1 Aug 2016' ),
    ( 100, 1, 1, '1 Jul 2016' ),
    ( 101, 1, 1, '1 Oct 2016' ),
    ( 102, 1, 1, '1 Oct 2016' ),
    ( 102, 1, 1, '1 Sep 2016' ),
    ( 103, 0, 1, '1 Oct 2016' ),
    ( 103, 1, 2, '1 Sep 2016' )
    ,
    ( 200, 0, 1, '1 Sep 2016' ),        -- No pass at all
    ( 201, 1, 1, '1 Sep 2016' ),        -- 1 pass at level 1 only
    ( 202, 1, 1, '1 Sep 2016' ),        -- 1 pass at each level 
    ( 202, 1, 2, '1 Sep 2016' ),        -- 1 pass at each level 
    ( 203, 1, 2, '1 Sep 2016' ),        -- 1 pass at level 2 only 
    ( 204, 0, 1, '1 Sep 2016' ),        -- No pass at either level
    ( 204, 0, 2, '1 Sep 2016' )         -- No pass at either level

    SELECT ID, 
        CASE 
            WHEN SUM( CAST( PASSED AS INT ) ) >= COUNT( DISTINCT LEVEL )
              AND COUNT( DISTINCT LEVEL ) = ( SELECT COUNT( DISTINCT LEVEL ) FROM @levels)
            THEN 1
            ELSE 0 
        END overallPass
    FROM @results
    GROUP BY ID
_

CREATEDATE列はあまり追加されていないようなので、計算に含めていません。また、誰かが同じレベルのコースに2回合格することは本当に意味がありますか(サンプルデータのID 100に従って)。彼らがコースを通過する順番は本当に重要ですか?もしそうなら、これは私のコードにSum of PASSED >= COUNT ( DISTINCT LEVEL )のバグを引き起こす可能性があります。データを事前に集計すると、これを解決できます。

_SELECT ID,
    CASE 
        WHEN SUM( CAST( PASSED AS INT ) ) >= COUNT( DISTINCT LEVEL )
          AND COUNT( DISTINCT LEVEL ) = ( SELECT COUNT( DISTINCT LEVEL ) FROM @levels)
        THEN 1
        ELSE 0 
    END overallPass
FROM ( SELECT ID, LEVEL, MAX( CAST( PASSED AS INT ) ) PASSED FROM @results GROUP BY ID, LEVEL ) x
GROUP BY ID
_

日付が本当に重要な場合は、投稿してください。少し複雑なクエリが必要になります。基本的には、_max date per ID_に関連付けられているPASSEDステータスです。

HTH

0
wBob