2012-05-08 7 views
5

日付のあるデータセットがあり、日付の順序が正しいかどうかを確認したいのですが。すべての場合において正しい注文のnull可能な日付の値を確認してください。

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 

日付が設けられている場合には、これは保持する必要があります:日付1 <日付2 < 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 

任意のアイデア?

EDIT:
私は(私は現実世界の問題に4を得た、と変更した上で与えた最初の例では3つの列よりも「日」の列にできるソリューションを探しています問題を単純化するためには3つにするが、この単純化では大きな特徴を失ったようだ)。 4列の例を更新しました。

+0

このルールに値を制約するだけで済みますか、行に対して「正しい/間違った」結果を得る必要はありますか? – Oded

+0

既存のデータに対する「正しい/間違った」チェックです。 – Josien

+0

したがって、行内のデータがルールに準拠しているかどうかを返す必要がありますか? – Oded

答えて

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;そこだけで起こるのを待って次のミレニアムのバグです;)

はEDIT:編集あなたは日付の比較選択の上ケースを使用している場合、最初のパラメータを返すISNULL関数を使用できる4つのフィールド

+0

この例では、3つのカラム、ありがとうございました。私はもっ​​と多くの列があるときにも動作するものを探しています。 – Josien

+3

@ Josien:4つのフィールド用に編集されました。主なことは、式は、元のバージョンではなく、指数関数的に増加するヌルフィールドのすべての組み合わせをチェックする必要がなく、線形に増加することです。可変数のフィールドで動作するものを探しているのであれば、通常は「通常の」SQLの範囲を超えており、何らかのストリング構築とEXECに依存しています。 – njr101

+0

素敵な解決策は、魅力のように動作します!私はミレニアムのバグのリスクで私のチャンスを取るでしょう:-) – Josien

1

を処理するために、それはnullではなく、firsがnullの場合は2番目の値です。私は

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 
+0

3つのカラム、ありがとうございました。私はもっ​​と多くの列があるときにも動作するものを探しています。 – Josien

+0

@Diego:このソリューションは動作しません。 date1が1950、date2がnull、date3が1949であるとします。式はtrueを返しますが、日付は正しい順序ではありません。比較を行うときは、合体を使用してヌル値をスキップする必要があります。 – njr101

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句の後に新しい行を追加するだけです。

関連する問題