こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

締切り済みの質問

SQLについて

SQLについてわからないのでご教授ください。

TABLE AAA

コード 適用開始日   適用終了日   
------ ----------- -----------
aaa 20100101 99999999
bbb 20100101 20100531
bbb 20100601 99999999
ccc 20100101 20110711
ccc 20110712 99999999


TABLE BBB

コード 適用開始日   適用終了日   
------ ----------- -----------
aaa 20100101 99999999
bbb 20100101 20100531
ccc 20100101 20110711




・テーブルBBBの適用終了日が'99999999'のコードは
テーブルAAAでは適用終了日が'99999999'の1レコードのみ。

・テーブルBBBの適用終了日が'20100531'などの'99999999'以外は
テーブルAAAでは適用終了日が'20100531'のレコードと、翌日'20100601'が適用開始日に設定され
'99999999'が適用終了日に設定されたレコードの2レコードが存在。

上記2つが正常の状態です。
これらの条件に反する異常を検知するようなSQLを作りたいです。

たとえば、テーブルAAAのレコード[bbb 20100601 99999999]がない場合、
実行結果としてコード「bbb」が出力されるようなSQLが欲しいです。
異常がなければ、「なにも選択されませんでした。」でよいです。


条件として、
・テーブルAAAでは「コード」「適用開始日」がPK
・テーブルAAAでは同じコードの「適用開始日」「適用終了日」の期間がかぶることはない
・テーブルAAAでは同じコードで3レコード以上は存在しない
  (たとえば20100101~20100531、20100601~20100931、20101001~20101231の3つの期間は存在しない)


実行結果はあくまで私の考えで、
異常を検知できればどのような形でも大丈夫です。

なにかあれば補足します。

どうぞよろしくお願い致します。

投稿日時 - 2011-05-27 08:13:31

QNo.6766492

困ってます

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(3)

ANo.3

ちょっと違いますね。訂正版です。

WITH CCC AS (
SELECT コード, TO_CHAR(TO_DATE(適用終了日, 'YYYYMMDD') + 1, 'YYYYMMDD') AS 適用開始日, '99999999' AS 適用終了日
FROM BBB
WHERE 適用終了日 <> '99999999'
)
SELECT DISTINCT コード FROM
((
SELECT コード, 適用開始日, 適用終了日 FROM AAA
MINUS
SELECT コード, 適用開始日, 適用終了日 FROM BBB
MINUS
SELECT コード, 適用開始日, 適用終了日 FROM CCC
)
UNION ALL
(
SELECT コード, 適用開始日, 適用終了日 FROM BBB
UNION ALL
SELECT コード, 適用開始日, 適用終了日 FROM CCC
MINUS
SELECT コード, 適用開始日, 適用終了日 FROM AAA
))
/

投稿日時 - 2011-05-27 16:15:31

お礼

お返事が遅くなり申し訳ありません。

ご回答ありがとうござます!
これを参考に考えさせていただきます。

投稿日時 - 2011-05-31 07:26:09

ANo.2

こんな感じですか

SELECT コード, 適用開始日, 適用終了日 FROM AAA
MINUS
SELECT コード, 適用開始日, 適用終了日 FROM BBB
MINUS
SELECT コード, TO_CHAR(TO_DATE(適用終了日, 'YYYYMMDD') + 1, 'YYYYMMDD'), '99999999'
FROM BBB
WHERE 適用終了日 <> '99999999'
/

投稿日時 - 2011-05-27 14:24:33

ANo.1

たとえば、

/* BBBの適用終了日が'99999999'の異常データ取得 */
select BBB.コード
from BBB
where BBB.適用終了日 = '99999999'
and exists ( --AAAに'99999999'以外のレコードがあるか
select *
from AAA
where AAA.コード = BBB.コード
and AAA.適用終了日 != '99999999')
union all
/* BBBの適用終了日が'99999999'以外の異常データ取得 */
select BBB.コード
from BBB
where BBB.適用終了日 != '99999999'
and not (
exists ( --AAAの適用終了日がBBBの適用終了日と同一レコードがあるか
select *
from AAA
where AAA.コード = BBB.コード
and AAA.適用終了日 = BBB.適用終了日)
and exists ( --AAAの適用開始日がBBBの適用終了日+1日かつ適用終了日が'99999999'のレコードがあるか
select *
from AAA
where AAA.適用開始日 = to_char(to_date(BBB.適用終了日,'yyyymmdd')+1,'yyyymmdd')
and AAA.適用終了日 = '99999999'));

とかでどうでしょうか。

投稿日時 - 2011-05-27 10:25:00

お礼

お返事が遅くなり申し訳ありません。

ご回答ありがとうござます!
これを参考に考えさせていただきます。

投稿日時 - 2011-05-31 07:26:18

あなたにオススメの質問