3

2 つのテーブル(SQL Fiddle)があるとします。1 つはさまざまなタイムスタンプで値を記録しており、もう 1 つは最も近い値をサンプリングする ID と日時を示しています。Kevin Meade のNEAREST NEIGHBOR PREFERENCE LOW (ただし、SQL Server 2008) に似たものを使用して、指定された ID の (null 以外の値) を、ターゲット (国勢調査) の日付に最も近いが、(国勢調査) の日付以降ではなく見つけたいと考えています。国勢調査の日付に一致する行がある場合は、その行を使用します (null 値がない場合)。国勢調査の日付より前の行がない場合は、国勢調査の日付より前ではなく最も近い行を見つけて、その行を使用します。

最初のテーブル:

CREATE TABLE Recorded_Vent_Types
    ([PAT_ENC_CSN_ID] int, [RECORDED_TIME] datetime, [MEAS_VALUE] varchar(9));

INSERT INTO Recorded_Vent_Types
    ([PAT_ENC_CSN_ID], [RECORDED_TIME], [MEAS_VALUE])
VALUES
    (11117777,  '2013-06-08 19:36:00.000',  'SIMV/PRVC'),
    (11117777,  '2013-06-08 22:21:00.000',  'PRVC/AC'),
    (11117777,  '2013-06-09 00:10:00.000',  NULL),
    (11117777,  '2013-06-09 03:00:00.000',  'SIMV/PRVC'),
    (11117777,  '2013-06-09 23:59:00.000',  'SIMV/PRVC'),
    (11117777,  '2013-06-10 00:00:00.000',  'NAVA'),
    (11117777,  '2013-06-10 00:20:00.000',  'PS'),
    (11117777,  '2013-06-10 00:25:00.000',  NULL),
    (555999,    '2013-06-08 00:36:00.000',  NULL),
    (555999,    '2013-06-08 22:21:00.000',  'PRVC/AC'),
    (555999,    '2013-06-09 00:10:00.000',  'SIMV/PRVC'),
    (555999,    '2013-06-11 23:15:00.000',  'BIVENT'),
    (555999,    '2013-06-12 00:00:00.000',  NULL),
    (555999,    '2013-06-12 00:20:00.000',  'PS');

2 番目のテーブル:

CREATE TABLE Census
    ([PAT_ENC_CSN_ID] int, [CENSUS_TIME] datetime);

INSERT INTO Census
    ([PAT_ENC_CSN_ID], [CENSUS_TIME])
VALUES
    (11117777, '2013-06-08 00:00:00'),
    (11117777, '2013-06-09 00:00:00'),
    (11117777, '2013-06-10 00:00:00'),
    (11117777, '2013-06-11 00:00:00'),
    (555999, '2013-06-08 00:00:00'),
    (555999, '2013-06-09 00:00:00'),
    (555999, '2013-06-11 00:00:00'),
    (555999, '2013-06-12 00:00:00');

これは、特定の ID の 1 つのテーブル内で同様のものに対する Meade 氏の Oracle コードです。

select *
from claim_history
where claim_id = 1
and status_date =
   (
    select min(status_date)
    from (
          select max(status_date) status_date
          from claim_history
          where claim_id = 1
          and status_date <= sysdate-3
          union all
          select min(status_date)
          from claim_history
          where claim_id = 1
          and status_date > sysdate-3
         )
   )
/

私の望ましい結果セット:

PAT_ENC_CSN_ID    CENSUS_TIME           RECORDED_TIME               MEAS_VALUE
555999      June, 08 2013 00:00:00+0000 June, 08 2013 22:21:00+0000 PRVC/AC
555999      June, 09 2013 00:00:00+0000 June, 08 2013 22:21:00+0000 PRVC/AC
555999      June, 11 2013 00:00:00+0000 June, 09 2013 00:10:00+0000 SIMV/PRVC
555999      June, 12 2013 00:00:00+0000 June, 11 2013 23:15:00+0000 BIVENT
11117777    June, 08 2013 00:00:00+0000 June, 08 2013 19:36:00+0000 SIMV/PRVC
11117777    June, 09 2013 00:00:00+0000 June, 08 2013 22:21:00+0000 PRVC/AC
11117777    June, 10 2013 00:00:00+0000 June, 10 2013 00:00:00+0000 NAVA
11117777    June, 11 2013 00:00:00+0000 June, 10 2013 00:20:00+0000 PS

@Gordon Linoff は、国勢調査の時間と記録された時間の間の日付差の絶対値を使用するというアイデアをくれました。これにより、@bobs ソリューションhereを変更することになりました。

SELECT * FROM
    (
    SELECT rvt.PAT_ENC_CSN_ID, CENSUS_TIME, RECORDED_TIME, MEAS_VALUE, ABS(DATEDIFF(s, c.CENSUS_TIME, RECORDED_TIME)) diff,
        ROW_NUMBER() OVER (PARTITION BY rvt.PAT_ENC_CSN_ID, c.CENSUS_TIME ORDER BY ABS(DATEDIFF(s, c.CENSUS_TIME, RECORDED_TIME))) AS SEQUENCE
    FROM Recorded_Vent_Types rvt join Census c on rvt.PAT_ENC_CSN_ID=c.PAT_ENC_CSN_ID
    WHERE MEAS_VALUE IS NOT NULL
    ) as m
WHERE SEQUENCE = 1
ORDER BY PAT_ENC_CSN_ID,CENSUS_TIME
;

ただし、これは (絶対) 最も近い記録時刻を返します。国勢調査時刻より前の記録時刻は優先されません。結果:

PAT_ENC_CSN_ID    CENSUS_TIME           RECORDED_TIME               MEAS_VALUE
555999      June, 08 2013 00:00:00+0000 June, 08 2013 22:21:00+0000 PRVC/AC
555999      June, 09 2013 00:00:00+0000 June, 09 2013 00:10:00+0000 SIMV/PRVC
555999      June, 11 2013 00:00:00+0000 June, 11 2013 23:15:00+0000 BIVENT
555999      June, 12 2013 00:00:00+0000 June, 12 2013 00:20:00+0000 PS
11117777    June, 08 2013 00:00:00+0000 June, 08 2013 19:36:00+0000 SIMV/PRVC
11117777    June, 09 2013 00:00:00+0000 June, 08 2013 22:21:00+0000 PRVC/AC
11117777    June, 10 2013 00:00:00+0000 June, 10 2013 00:00:00+0000 NAVA
11117777    June, 11 2013 00:00:00+0000 June, 10 2013 00:20:00+0000 PS
4

1 に答える 1

0

これは、Oracle と SQL Server の両方で相関サブクエリとして実行できます。これは、トップ 1 を除いてほぼ標準の SQL であるためです。

クエリは次のとおりです。

select *,
       (select top 1 PAT_ENC_CSN_ID
        from census c
        where c.census_time <= rvt.recorded_time
        order by (case when c.census_time <= rvt.recorded_time then 1 else 0
                  end) desc,
                 (case when c.census_time <= rvt.recorded_time then c.census_time
                  end) desc,
                 c.census_time asc
       ) as nearestVal
from Recorded_Vent_Types rvt

order byサブクエリは、クエリのキーであるに基づいて 1 つの行を返します。3 つの部分があります。

最初のものは、最初に記録された時間の前にすべての国勢調査時間を置きます。2 番目はこれらを国勢調査時刻の降順で並べ替え、3 番目は残りを昇順で並べ替えます。最後の 2 つを次のように置き換えたいと思います。

abs(c.census_time - rvt.recorded_time)

これは論理的にそれが行うことだからです。で動作しないため、残念ながら動作しませabs()datetime。そして、datediff()関数またはcaseステートメントを使用する必要があり、より複雑に見え始めます。

于 2013-06-10T22:00:30.707 に答える