レスポンスの良いクエリを教えてください。

ベイラム
2013-10-16 15:29 1864 1
SQL文についての質問です。

なるべくレスポンスの良いクエリを考えています。
テーブルはAとBの2つあるとします。
/は各項目の区切りを表しています。
NullはNULL値(ブランク)を表しています。

【テーブルA】

オーダNo / 科目1 / 科目2 / 科目3 / 申請日 / 生徒名 / 取得区分
10001 / Jyoho / Keizai / Keiei / 20130901 / Ishii / 0
10002 / Jyoho / Keiei / Null / 20130901 / Numata / 1
10003 / Keizai / Null / Null / 20130903 / Wada / 0


【テーブルB】

オーダNo / 科目 / 取得日
10002 / Jyoho / 20130912
10002 / Keizai / 20130912


テーブルAはまだ取得日がないデータで
取得日が確定すると
テーブルAの情報をもとにテーブルB
が作成されるイメージです。

そして、出力したいデータはすべてを網羅したデータなんです!
取得区分:1の場合は、テーブルBから、0の場合はテーブルAの列持ちの
科目1~3を取得したいです。

オーダNo / 科目 / 申請日 / 取得日
10001 / Jyoho / 20130901 / Null
10001 / Keizai / 20130901 / Null
10001 / Keiei / 20130901 / Null
10002 / Jyoho / 20130901 / 20130912
10002 / Keizai / 20130901 / 20130912
10003 / Keizai / 20130903 / Null


一応作成したクエリは下記のUNIONを使ったものなんですけど
よりレスポンスが良くなるクエリがありましたら教えていただきたいです。

SELECT テーブルB.オーダNo, テーブルB.科目, テーブルA.申請日, テーブルB.取得日
FROM テーブルB INNER JOIN テーブルA ON テーブルA.オーダNo = テーブルB.オーダNo
UNION
SELECT オーダNo, 科目1, 申請日, NULL AS 取得日
FROM テーブルA AS テーブルA_3
WHERE (取得区分 = 0) AND (科目1 IS NOT NULL)
UNION
SELECT オーダNo, 科目2, 申請日, NULL AS 取得日
FROM テーブルA AS テーブルA_2
WHERE (取得区分 = 0) AND (科目2 IS NOT NULL)
UNION
SELECT オーダNo, 科目3, 申請日, NULL AS 取得日
FROM テーブルA AS テーブルA_1
WHERE (取得区分 = 0) AND (科目3 IS NOT NULL)

コメント

2013年 10月 18日 (12:24)
こんにちは。
イノ(inno)です。

クエリは下記のようにしてみてください。
ですが、そもそも【テーブルA】の作りが間違ってます。
あまりイイと言えるテーブル構成ではありません。
それと質問内容の【テーブルA】のデータの中で[オーダNo]が10002で[科目2]のデータが「Keiei」になっていますが、
「Keizai」ではないでしょうか?
そうしないと結果がおかしくなりますが。。。。ご検討を。。。

-- ######################################################################

SELECT A.[オーダNo], A.[科目], A.[申請日], B.[取得日]
FROM
(
SELECT
[オーダNo]
,CASE Code WHEN 1 THEN [科目1] WHEN 2 THEN [科目2] WHEN 3 THEN [科目3] END [科目]
,[申請日]
,[生徒名]
,[取得区分]
FROM #TableA AS A
, (
SELECT 1 Code UNION ALL
SELECT 2 Code UNION ALL
SELECT 3 Code
) AS B
WHERE CASE Code WHEN 1 THEN [科目1] WHEN 2 THEN [科目2] WHEN 3 THEN [科目3] END IS NOT NULL

) AS A
LEFT OUTER JOIN #TableB AS B
ON A.[オーダNo] = B.[オーダNo] AND A.[科目] = B.[科目]
ORDER BY A.[オーダNo], A.[科目]

-- ######################################################################

他の方の為テスト用のSQLを作成しました。
一時テーブル作成からデータ登録まで。。。
下記のSQLで試してください。

-- #### 一時テーブル作成
CREATE TABLE #TableA
(
[オーダNo] int
,[科目1] varchar(10)
,[科目2] varchar(10)
,[科目3] varchar(10)
,[申請日] varchar(10)
,[生徒名] varchar(10)
,[取得区分] tinyint
)
GO

CREATE TABLE #TableB
(
[オーダNo] int
,[科目] varchar(10)
,[取得日] varchar(10)
)
GO

-- #### データ登録
INSERT INTO #TableA
SELECT 10001,'Jyoho','Keizai','Keiei','20130901','Ishii',0 UNION ALL
SELECT 10002,'Jyoho','Keizai',NULL,'20130901','Numata',1 UNION ALL
SELECT 10003,'Keizai',NULL,NULL,'20130903','Wada',0

INSERT INTO #TableB
SELECT 10002,'Jyoho','20130912' UNION ALL
SELECT 10002,'Keizai','20130912'
GO

-- #### 結果
SELECT A.[オーダNo], A.[科目], A.[申請日], B.[取得日]
FROM
(
SELECT
[オーダNo]
,CASE Code WHEN 1 THEN [科目1] WHEN 2 THEN [科目2] WHEN 3 THEN [科目3] END [科目]
,[申請日]
,[生徒名]
,[取得区分]
FROM #TableA AS A
, (
SELECT 1 Code UNION ALL
SELECT 2 Code UNION ALL
SELECT 3 Code
) AS B
WHERE CASE Code WHEN 1 THEN [科目1] WHEN 2 THEN [科目2] WHEN 3 THEN [科目3] END IS NOT NULL

) AS A
LEFT OUTER JOIN #TableB AS B
ON A.[オーダNo] = B.[オーダNo] AND A.[科目] = B.[科目]
ORDER BY A.[オーダNo], A.[科目]


-- #### 実行結果
オーダNo 科目 申請日 取得日
10001 Jyoho 20130901 NULL
10001 Keiei 20130901 NULL
10001 Keizai 20130901 NULL
10002 Jyoho 20130901 20130912
10002 Keizai 20130901 20130912
10003 Keizai 20130903 NULL