5

日付を含むデータ セットがあり、日付の順序が正しいかどうかを確認したいと考えています。

RecordID   Date1        Date2        Date3        Date4
1          2011-05-10   2011-08-16   NULL         2011-11-22
2          NULL         2012-02-03   2012-02-27   2012-03-05
3          2011-05-30   2011-05-11   2011-08-17   2011-09-15
4          2011-05-30   NULL         NULL         NULL

日付が提供される場合は常に、Date1 < Date2 < Date3 < Date4 を保持する必要があります。レコードに特定の日付の NULL 値が含まれている場合、NULL でない日付の間でチェックを行う必要があります。だから、これは私が望む結果です:

RecordID   Date1        Date2        Date3        Date4        CheckDates
1          2011-05-10   2011-08-16   NULL         2011-11-22   correct
2          NULL         2012-02-03   2012-02-27   2012-03-05   correct
3          2011-05-30   2011-05-11   2011-08-17   2011-09-15   incorrect
4          2011-05-30   NULL         NULL         NULL         correct

これについては広範な CASE ステートメントを書きましたが、もっと洗練された解決策があるはずです。

CASE
  WHEN Date1 IS NULL AND Date2 IS NULL AND Date3 IS NULL AND Date4 IS NULL THEN 'correct'
  WHEN Date1 IS NULL AND Date2 IS NULL AND Date3 IS NULL AND Date4 IS NOT NULL THEN 'correct'
  WHEN Date1 IS NULL AND Date2 IS NULL AND Date3 IS NOT NULL AND Date4 IS NULL THEN 'correct'
  WHEN Date1 IS NULL AND Date2 IS NULL AND Date3 IS NOT NULL AND Date4 IS NOT NULL AND Date3 < Date4 THEN 'correct'
  ...
  ELSE 'incorrect'
END

何か案は?

編集:
上記の最初の例の 3 つの列よりも多くの「日付」列を許可するソリューションを探しています (実際の問題では 4 つあり、問題を単純化するために 3 つに変更しました。しかし、私はこの単純化で重要な特徴を失ったようです)。4 列の例を更新しました。

4

3 に答える 3

7

とを使用ISNULLCOALESCEて、null 値をスキップできます。日付が欠落している場合は、常にチェックに合格する日付に置き換えてください。

CASE
  WHEN (ISNULL(Date1, '01/01/1900') < COALESCE(Date2, Date3, Date4, '01/01/3000'))
   AND (ISNULL(Date2, '01/01/1900') < COALESCE(Date3, Date4, '01/01/3000'))
   AND (ISNULL(Date3, '01/01/1900') < COALESCE(Date4, '01/01/3000'))
  THEN 'correct'
  ELSE 'incorrect'
END

これは、あなたの「実際の」日付が 1900 から 3000 の範囲を外れることはないと仮定しています。次のミレニアム バグが発生するのを待っています ;)

編集: 4 つのフィールドを処理するように編集

于 2012-05-08T14:45:47.370 に答える
1

日付を比較する選択でケースを使用し、最初のパラメーターがnullでない場合は最初のパラメーターを返し、最初のパラメーターがnullの場合は2番目のパラメーターを返すISNULL関数を使用できます。

この場合、開始日を早い日付として設定し、終了日を古い日付として設定しました。

select date1,date2,date3,
     case
        when isnull(date1,'01/01/1900') <isnull(date2,'01/01/2100') and isnull(date2,'01/01/1900') <isnull(date3,'2100') then 'OK'
        else 'not OK'
    end
from testDates
于 2012-05-08T14:52:43.857 に答える
1

別のアプローチを次に示します。

WITH data (
  RecordID,  Date1      , Date2      , Date3      , Date4
) AS (
  SELECT 1, '2011-05-10','2011-08-16', NULL       ,'2011-11-22' UNION ALL
  SELECT 2,  NULL       ,'2012-02-03','2012-02-27','2012-03-05' UNION ALL
  SELECT 3, '2011-05-30','2011-05-11','2011-08-17','2011-09-15' UNION ALL
  SELECT 4, '2011-05-30', NULL       , NULL       , NULL
)
SELECT
  *,
  CheckDates = (
    SELECT
      MAX(CASE IdRank WHEN DateRank THEN 'correct' ELSE 'incorrect' END)
    FROM (
      SELECT
        IdRank   = ROW_NUMBER() OVER (ORDER BY ID),
        DateRank = ROW_NUMBER() OVER (ORDER BY Date)
      FROM (
        VALUES
          (1, Date1),
          (2, Date2),
          (3, Date3),
          (4, Date4)
      ) s (ID, Date)
      WHERE Date IS NOT NULL
    ) s
  )
FROM data

出力は次のとおりです。

RecordID    Date1      Date2      Date3      Date4      CheckDates
----------- ---------- ---------- ---------- ---------- ----------
1           2011-05-10 2011-08-16 NULL       2011-11-22 correct
2           NULL       2012-02-03 2012-02-27 2012-03-05 correct
3           2011-05-30 2011-05-11 2011-08-17 2011-09-15 incorrect
4           2011-05-30 NULL       NULL       NULL       correct

チェック式は@njr's answer のものよりも複雑ですが、より多くの列をサポートするためにスクリプトをスケーリングする必要がある場合に効果があると思いますVALUES。句の後に新しい行を追加するだけで済みます。

于 2012-05-10T09:22:34.337 に答える