-1

まだ最適な解決策が見つからないため、この質問を再投稿しています。

患者の血液サンプル情報を取得するテーブルを設計しています。これには、患者 ID と収集日 (患者の血液サンプルが収集された日付) があります。

テーブルには、episode_number、episode_start_date、episode_end_date の 3 つの列が追加されています。エピソードは 30 日間の時間枠にすぎません。30 日以内に収集されたサンプルはすべて同じエピソードに属します。たとえば、患者が最初の血液サンプルを 2013 年 1 月 1 日に提出し、次の血液サンプルを 2013 年 1 月 19 日に提出したとします。両方の収集日が同じ「30 日ウィンドウ」内にあるため、同じ episode_number (エピソード 1) に属します。このエピソードの開始日は最初の収集日 (2013 年 1 月 1 日) になり、終了日は開始日 + 30 日 (2013 年 1 月 30 日) になります。この日付範囲内に収集された任意の数の患者の血液サンプルは、episode_number = 1 に属します。

同じ患者が 2013 年 2 月 4 日に別の血液サンプルを提出したとします。この収集日は episode_number = 1 の 30 日間のウィンドウの外にあるため、新しい episode_number (エピソード 2) に属します。このエピソードの開始日は 2013 年 2 月 4 日で、終了日は 30 日後、つまり 2013 年 3 月 2 日です。

以下の例のようなテーブルがあるとします。

------------------------------------------------------------------------------------------
Patient ID | Collection_Date | Episode_Number     |Episode_Start_Date | Episode_End_Date |
1          | 2013-01-01      |                    |                   |                  |
1          | 2013-01-01      |                    |                   |                  |   
1          | 2013-01-05      |                    |                   |                  |
1          | 2013-02-04      |                    |                   |                  |  
1          | 2013-02-06      |                    |                   |                  |   
1          | 2013-05-01      |                    |                   |                  |
1          | 2013-08-01      |                    |                   |                  |
-------------------------------------------------------------------------------------------

上記のテキストで説明したロジックに基づいて、episode_number、episode_start_Date、episode_end_date を入力するクエリが必要です。クエリの結果は、以下に示すテーブルの値を入力する必要があります。

----------------------------------------------------------------------------------------
Patient ID | Collection_Date |Episode_number     |Episode_Start_Date| Episode_End_Date |
1          | 2013-01-01      |1                  |2013-01-01        | 2013-01-30       |
1          | 2013-01-01      |1                  |2013-01-01        | 2013-01-30       |
1          | 2013-01-05      |1                  |2013-01-05        | 2013-01-30       |
1          | 2013-02-04      |2                  |2013-02-04        | 2013-03-02       |
1          | 2013-02-06      |2                  |2013-02-04        | 2013-02-04       |
1          | 2013-05-01      |3                  |2013-05-01        | 2013-05-30       |
1          | 2013-08-01      |4                  |2013-08-01        | 2013-08-30       |
----------------------------------------------------------------------------------------

覚えておくべきこと:

  1. エピソード = 30 日間の時間枠
  2. 最初のエピソードの開始日 = 最初の収集日
  3. 最初のエピソードの終了日 = 最初のエピソードの開始日 + 30 日
  4. 同じ 30 日間のウィンドウ内で収集されたすべてのサンプルは、同じエピソードに属します。
  5. いずれかのサンプルの収集日が前の収集のエピソード終了日より後の場合、それはエピソード開始日 = 収集日である新しいエピソードに属します。エピソードの終了日 = 開始日 + 30 日。

私の質問が明確に理解できることを願っています。私のテーブルには 300 万を超えるレコードがあるため、機能するソリューションだけでなく、最適なパフォーマンスを実現するソリューションも必要です。どんな助け/提案も大歓迎です。

前もって感謝します!

アシッシュ

4

2 に答える 2

1

テーブルのデザインを変更するオプションがある場合は、Mike Sherill の回答をお勧めします。

オプションがない場合は、次のように動作するはずですが、パフォーマンスが低下する可能性があります。

with cte as
(select [Patient ID],
        min(Collection_Date) Collection_Date,
        1 Episode_Number,
        min(Collection_Date) Episode_Start_Date,
        Dateadd(d,29,min(Collection_Date)) Episode_End_Date
 from sampleTable
 group by [Patient ID]
 union all
 select s.[Patient ID],
        s.Collection_Date Collection_Date,
        c.Episode_Number+1 Episode_Number,
        s.Collection_Date Episode_Start_Date,
        Dateadd(d,29,s.Collection_Date) Episode_End_Date
 from cte c
 join sampleTable s 
   on c.[Patient ID] = s.[Patient ID] and 
      c.Episode_End_Date < s.Collection_Date and
      not exists (select null
                  from sampleTable i
                  where c.[Patient ID] = i.[Patient ID] and
                        c.Episode_End_Date < i.Collection_Date and
                        i.Collection_Date < s.Collection_Date)
 )
select cte.[Patient ID],
       st.Collection_Date,
       cte.Episode_Number,
       cte.Episode_Start_Date,
       cte.Episode_End_Date
from cte
join sampleTable st 
  on st.[Patient ID] = cte.[Patient ID] and 
     st.Collection_Date between cte.Episode_Start_Date and cte.Episode_End_Date 
option (maxrecursion 0)

ここでSQLFiddle 。

于 2013-06-10T18:16:20.423 に答える
1

(これはしばらくそのままにしておきますが、これは、collection_date が episode_start_date と episode_end_date の間にある必要があるという、表現されていない制約を実装していません。)

この表の一部を見てみましょう。

Patient ID | Collection_Date |Episode_number     |Episode_Start_Date| Episode_End_Date |
1          | 2013-01-01      |1                  |2013-01-01        | 2013-01-30       |
1          | 2013-01-01      |1                  |2013-01-01        | 2013-01-30       |

行を複製します。このテーブルにはキーがありません。

これらの 2 つの同一の行は、どのような違いを示しているのでしょうか?

この種のテーブルは、別の ID 番号だけでなく、実際のキーを要求します。

患者のエピソードに関する情報を格納するテーブルは、おそらく次のようにする必要があります。

create table patient_episodes (
  patient_id integer not null,
  episode_number integer not null
    check (episode_number > 0),
  primary key (patient_id, episode_number),
  foreign key (patient_id, episode_number) 
    references samples (patient_id, episode_number),

  episode_start_date date not null,
  episode_end_date date not null,
  check (episode_end_date = episode_start_date + interval '30 days')
);

患者のエピソードは空であるため、最初に患者のエピソードからサンプルへの外部キー参照を宣言する必要があります。両方のテーブルにデータが入力されて安定した後も、そのままにしておくべきかどうかはわかりません。(おそらくそうではありませんが、私は推測したくありません。)

キーがないため、サンプルのテーブルはまだ構造的に問題があります。この問題をどのように解決するかは、patient_episodes テーブルの構造に影響を与えます。

于 2013-06-10T18:10:17.330 に答える