9

以前に回答済みの質問を投稿しましたが、これについてもクエリが必要です。このようなデータを含むテーブル構造があります(日付はdd/mm/yyyyの形式です)。

ID    Account Number    Unit    Admit_Date    Disch_Date
1     1001              w32     01/04/2012    
2     1002              w32     01/04/2012    01/04/2012
3     1001              ccu     03/04/2012
4     1001              w33     05/04/2012
5     1003              cicu    04/04/2012
6     1001              ccu     07/04/2012
7     1001              ccu     07/04/2012    10/04/2012
8     1003              w33     05/04/2012
9     1003              w33     05/04/2012    08/04/2012

基本的に、この表は、特定の病棟に入院し、病棟間を移動し、最終的に同日または数日後に退院する患者を扱います。クエリから期待される結果は次のようになります。

Account_Number                                 No. Of Days
1001              01/04/2012    03/04/2012      2
1001              03/04/2012    05/04/2012      2
1001              05/03/2012    07/04/2012      2
1001              07/04/2012    10/04/2012      3
1002              01/04/2012    01/04/2012      0
1003              04/04/2012    05/04/2012      1
1003              05/04/2012    08/04/2012      3

退院日フィールドは、患者が退院したときにのみ入力されるため、入院日と退院日の両方を含む患者の移動の各日付の日付差を計算したいと思います。

MS Access 2003 を使用しています。

誰かがこれで私を助けてくれることを願っています。

4

1 に答える 1

6

無関係なデータを除外する

複雑なクエリでは、アートの一部としてクエリを1つずつ作成し、テストを進めていきます。

テーブル名はPatientMovementsであり、次のようになっていると思います。

ID={6,7}とID={8,9}のような行のペアが与えられた場合、患者(アカウント番号)、ユニット、および退院日がnullの入院日がある行は無視されると言うの正しいです。また、同じ患者、ユニット、および入院日であるが、ヌルではない退院日についての記録。

したがって、ステップ1は、データベースに記録されているテーブルから無関係なデータを除外して、作業する必要のある行を生成することです。これは、2つのデータセットの和集合です。

  1. null以外の除隊日を持つ行。
  2. 退院日がヌルであるが、同じアカウント、ユニット、および入場日の行がない行。

明らかに、UNIONの最初の部分は次のとおりです。

SELECT * FROM PatientMovements WHERE DischargeDate IS NOT NULL

それほど明白ではありませんが、UNIONの2番目の部分は次のとおりです。

SELECT *
  FROM PatientMovements AS p1
 WHERE DischargeDate IS NULL
   AND NOT EXISTS
       (SELECT *
          FROM PatientMovements AS P2
         WHERE P1.Account   = P2.Account
           AND P1.Unit      = P2.Unit
           AND P1.AdmitDate = P2.AdmitDate
           AND P2.DischargeDate IS NOT NULL
       )

これで、これらを1つの結果セットに組み合わせることができます。

SELECT *
  FROM PatientMovements
 WHERE DischargeDate IS NOT NULL
UNION
SELECT *
  FROM PatientMovements AS p1
 WHERE DischargeDate IS NULL
   AND NOT EXISTS
       (SELECT *
          FROM PatientMovements AS P2
         WHERE P1.Account   = P2.Account
           AND P1.Unit      = P2.Unit
           AND P1.AdmitDate = P2.AdmitDate
           AND P2.DischargeDate IS NOT NULL
       )

上記のクエリは、IDが1..5、7、および9の行を返すことを確認することで確認できます。

警告:テストされていないコード。この回答のSQLはいずれもDBMSの近くにないため、テストされていません。

以前に学んだ教訓を適用する

次に、他の質問からの学習を適用して、データの順序付けや日付の違いの計算などを行うことができます。唯一の問題は、クエリを2回書き出す必要があることです。これは、面倒です(MS Access2003が「WITH」をサポートしていない場合)。句または共通テーブル式)。


しかし、この必要な出力を取得するための単一のクエリはありませんか?

もちろん、UNIONは単一のクエリです。私はあなたがただ書くことができると思います:

SELECT *
  FROM PatientMovements
 WHERE (DischargeDate IS NOT NULL)
    OR (DischargeDate IS     NULL
        AND NOT EXISTS
            (SELECT *
               FROM PatientMovements AS P2
              WHERE P1.Account   = P2.Account
                AND P1.Unit      = P2.Unit
                AND P1.AdmitDate = P2.AdmitDate
                AND P2.DischargeDate IS NOT NULL
            )
       )

クエリを実行するためのよりコンパクトな方法をすぐに考えることはできません。


UNIONを「その他の答え」に組み込む

他の質問に対する受け入れられた回答には、2つの可能な解決策があります(コメントによって修正され、再フォーマットされています)。

SELECT T1.ID, T1.AccountNumber, T1.Date, 
       MIN(T2.Date) AS NextDate, 
       DATEDIFF("D", T1.Date, MIN(T2.Date)) AS DaysDiff
  FROM YourTable T1
  JOIN YourTable T2
    ON T1.AccountNumber = T2.AccountNumber AND T2.Date > T1.Date

または:

SELECT ID, AccountNumber, Date, NextDate,
       DATEDIFF("D", Date, NextDate) AS DaysDiff
  FROM (SELECT ID, AccountNumber, Date,
               (SELECT MIN(Date) 
                  FROM YourTable T2
                 WHERE T2.AccountNumber = T1.AccountNumber
                   AND T2.Date > T1.Date
               ) AS NextDate
          FROM YourTable T1
        ) AS T

コメントに記載されているように、質問にテーブル名がない場合、回答に異なるテーブル名が表示されます。私がPatientMovementsと呼んだものは、この回答ではYourTableと呼ばれていました。もう1つの違いは、元の質問のデータにUnit列またはDischargeDate列が含まれていなかったことです。ただし、私が提供したUNIONクエリは、これらのクエリを実行するための関連データを提供するため、あとはYourTableの代わりに他の回答にUNIONクエリを書き込むだけです。これはにつながります:

SELECT T1.ID, T1.AccountNumber, T1.Date, 
       MIN(T2.Date) AS NextDate, 
       DATEDIFF("D", T1.Date, MIN(T2.Date)) AS DaysDiff
  FROM (SELECT *
          FROM PatientMovements
         WHERE (DischargeDate IS NOT NULL)
            OR (DischargeDate IS     NULL
                AND NOT EXISTS
                    (SELECT *
                       FROM PatientMovements AS P2
                      WHERE P1.Account   = P2.Account
                        AND P1.Unit      = P2.Unit
                        AND P1.AdmitDate = P2.AdmitDate
                        AND P2.DischargeDate IS NOT NULL
                    )
               )
       ) AS T1
  JOIN (SELECT *
          FROM PatientMovements
         WHERE (DischargeDate IS NOT NULL)
            OR (DischargeDate IS     NULL
                AND NOT EXISTS
                    (SELECT *
                       FROM PatientMovements AS P2
                      WHERE P1.Account   = P2.Account
                        AND P1.Unit      = P2.Unit
                        AND P1.AdmitDate = P2.AdmitDate
                        AND P2.DischargeDate IS NOT NULL
                    )
               )
       ) AS T2
    ON T1.AccountNumber = T2.Accountnumber AND T2.Date > T1.Date

または:

SELECT ID, AccountNumber, Date, NextDate,
       DATEDIFF("D", Date, NextDate) AS DaysDiff
  FROM (SELECT ID, AccountNumber, Date,
               (SELECT MIN(Date) 
                  FROM (SELECT *
                          FROM PatientMovements
                         WHERE (DischargeDate IS NOT NULL)
                            OR (DischargeDate IS     NULL
                                AND NOT EXISTS
                                    (SELECT *
                                       FROM PatientMovements AS P2
                                      WHERE P1.Account   = P2.Account
                                        AND P1.Unit      = P2.Unit
                                        AND P1.AdmitDate = P2.AdmitDate
                                        AND P2.DischargeDate IS NOT NULL
                                    )
                               )
                       ) AS T2
                 WHERE T2.Accountnumber = T1.AccountNumber
                   AND T2.Date > T1.Date
               ) AS NextDate
          FROM (SELECT *
                  FROM PatientMovements
                 WHERE (DischargeDate IS NOT NULL)
                    OR (DischargeDate IS     NULL
                        AND NOT EXISTS
                            (SELECT *
                               FROM PatientMovements AS P2
                              WHERE P1.Account   = P2.Account
                                AND P1.Unit      = P2.Unit
                                AND P1.AdmitDate = P2.AdmitDate
                                AND P2.DischargeDate IS NOT NULL
                            )
                       )
               ) AS T1
        ) AS T

したがって、注意深く、クエリをフラグメントで開発し、それらを一貫して組み合わせる限り、最も見栄えの悪いクエリを飼いならすことができます。

一般的なテーブル式

SQL標準には「共通テーブル式」(CTE)、別名「WITH句」があり、これにより作業がさらに簡単になることに注意してください。

WITH YourTable AS
   (SELECT *
      FROM PatientMovements
     WHERE (DischargeDate IS NOT NULL)
        OR (DischargeDate IS     NULL
            AND NOT EXISTS
                (SELECT *
                   FROM PatientMovements AS P2
                  WHERE P1.Account   = P2.Account
                    AND P1.Unit      = P2.Unit
                    AND P1.AdmitDate = P2.AdmitDate
                    AND P2.DischargeDate IS NOT NULL
                )
           )
     )
SELECT T1.ID, T1.AccountNumber, T1.Date, 
       MIN(T2.Date) AS NextDate, 
       DATEDIFF("D", T1.Date, MIN(T2.Date)) AS DaysDiff
  FROM YourTable T1
  JOIN YourTable T2
    ON T1.AccountNumber = T2.AccountNumber AND T2.Date > T1.Date

または:

WITH YourTable AS
   (SELECT *
      FROM PatientMovements
     WHERE (DischargeDate IS NOT NULL)
        OR (DischargeDate IS     NULL
            AND NOT EXISTS
                (SELECT *
                   FROM PatientMovements AS P2
                  WHERE P1.Account   = P2.Account
                    AND P1.Unit      = P2.Unit
                    AND P1.AdmitDate = P2.AdmitDate
                    AND P2.DischargeDate IS NOT NULL
                )
           )
     )
SELECT ID, AccountNumber, Date, NextDate,
       DATEDIFF("D", Date, NextDate) AS DaysDiff
  FROM (SELECT ID, AccountNumber, Date,
               (SELECT MIN(Date) 
                  FROM YourTable T2
                 WHERE T2.AccountNumber = T1.AccountNumber
                   AND T2.Date > T1.Date
               ) AS NextDate
          FROM YourTable T1
        ) AS T

CTEを使用する主な利点の1つは、オプティマイザーが使用されるすべての場所でテーブル式が同じであると明示的に通知されるのに対し、何度か書き出されると、その共通性を見つけられない可能性があることです。さらに、クエリを数回書き出すと、編集エラーのために2つのクエリが実際にはわずかに異なる可能性があります。その可能性はCTEによって排除されています。現在の状況における他の利点は、CTEを他の質問の解決策と組み合わせることが子供の遊びであったことでした。

残念ながら、MSAccess2003がCTEをサポートしている可能性はほとんどありません。私はあなたの痛みを共有します。私が使用しているDBMSも主にそうではありません。

于 2012-04-11T01:39:17.163 に答える