- PR -

空行の場合の処理

1
投稿者投稿内容
landy
会議室デビュー日: 2007/09/14
投稿数: 12
お住まい・勤務地: 中部
投稿日時: 2007-09-14 20:16
初めまして
早速なのですが、

mst_member
--------------
m_id| name
1| 社員A
2| 社員B
3| 社員C
--------------

tbl_data
-------------------------
m_id|year|month|day |mess
1 |2007| 9| 14|テスト
-------------------------

上記の様な二つのテーブルがあったとします
(上記はすごく簡略化してますが)

やりたいことは指定の社員の名前と指定日のメッセージを取り出したいのですが、
仮にメッセージは無くても名前だけは取り出したいわけです。
(要するにmessはNULLでも良い)

仮に
SELECT m_id , name , mess FROM mst_member as A , tbl_data as B WHERE A.m_id = B.m_id AND A.m_id = 1 AND year = 2007 AND month = 9 AND day = 14
とした場合、予定通り
「1 社員A テスト」
として取得できるわけですが、日付が変わると当然データが無い為、
空行を返してきてしまいます(当たり前ですが)

その場合はmessをNULLか空白として社員コードと名前だけは取得したいわけです。
LEFT JOIN で結合しても日付条件が右側のテーブルにある為か空行になります。

今は社員コードと氏名だけを先に表示させ、
その後、VBの方で表から社員コードを取出して日付からmessを拾い、
無ければ空白を表示という形で2回ループ&SQL実行を行っておりまして、
1回に出来るならしたいのが本音であれこれ今日一日やったのですが
ちょっとくじけてきたので投稿することにしました。

ずばりの答えは無くとも構いませんが何かヒントだけでもお願い致します!
一郎
ぬし
会議室デビュー日: 2002/10/11
投稿数: 1081
投稿日時: 2007-09-14 20:28
あれ…?LEFT JOINでだめなんですか?

SELECT A.m_id, A.name, B.mess FROM mst_member as A
LEFT JOIN tbl_data as B ON B.year = 2007 AND B.month = 9 AND B.day = 14 AND B.m_id = A.m_id
WHERE AND A.m_id = 1

こんなんでよさそうですけど…。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2007-09-14 20:38
引用:

landyさんの書き込み (2007-09-14 20:16) より:
やりたいことは指定の社員の名前と指定日のメッセージを取り出したいのですが、
仮にメッセージは無くても名前だけは取り出したいわけです。
(要するにmessはNULLでも良い)


読んでて良く分からなかったのですが、要は mess というよりも tbl_data のレコードがない場合、ということですよね。

引用:

landyさんの書き込み (2007-09-14 20:16) より:
今は社員コードと氏名だけを先に表示させ、
その後、VBの方で表から社員コードを取出して日付からmessを拾い、
無ければ空白を表示という形で2回ループ&SQL実行を行っておりまして、
1回に出来るならしたいのが本音であれこれ今日一日やったのですが
ちょっとくじけてきたので投稿することにしました。


tbl_data のレコードがない場合といった、すなわち「0件」だけを特別扱いしたいということは、あくまでも表示の都合によるものだと思います。まあ、良くある要求仕様ですが。
こういう仕様は、RDB の枠組みから外れているので、RDB の中でひとつの SQL 一発で書くことがかならずしもきれいなコードではないと思います。今やられているような2回に分けるやりかたも、基本的には間違いではないでしょう。
LEFT JOIN や RIGHT JOIN でもできるのかもしれませんし、UNION や UNION ALL でもできるかもしれません。ただ、NULL が出てきたりして無駄に複雑になったりします。SQL の発行にコストのかかった昔ならば、SQL 一発でやることに価値はあったかもしれませんが、今ならあまり拘らなくても良いかもしれません。

--
unibon {B73D0144-CD2A-11DA-8E06-0050DA15BC86}
よっし〜。
ベテラン
会議室デビュー日: 2007/04/17
投稿数: 89
お住まい・勤務地: 北のほうの国
投稿日時: 2007-09-14 20:59
引用:

landyさんの書き込み (2007-09-14 20:16) より:

LEFT JOIN で結合しても日付条件が右側のテーブルにある為か空行になります。


おそらく LEFT JOIN 時にWHERE句に日付条件を含めているせいでしょう。
一郎さんが提示されているようにON句以降に日付条件を記載すれば大丈夫です。

JOIN 〜 ON 句を使わない外部結合の場合
・WHERE句の条件は「結合するとき」に適用される。

JOIN 〜 ON 句を使った外部結合の場合
・ON句の条件は「結合するとき」に適用される。
・WHERE句の条件は「結合した後」に適用される。(結合結果に対して)
 →今回の場合NULL値に対してここで日付条件をつけたため空行になったと思われます。


"JOIN 〜 ON 句を使わない外部結合"は使わないほうが身のためです。
landy
会議室デビュー日: 2007/09/14
投稿数: 12
お住まい・勤務地: 中部
投稿日時: 2007-09-15 10:22
皆さんありがとうございました
無事に思っている通りにデータ取出しができました!

>おそらく LEFT JOIN 時にWHERE句に日付条件を含めているせいでしょう。
>一郎さんが提示されているようにON句以降に日付条件を記載すれば大丈夫です。
おっしゃるとおりでした。

>JOIN 〜 ON 句を使った外部結合の場合
>・ON句の条件は「結合するとき」に適用される。
>・WHERE句の条件は「結合した後」に適用される。(結合結果に対して)
> →今回の場合NULL値に対してここで日付条件をつけたため空行になったと思われます
私の中でこの理解が抜けておりましてONの後は二つのテーブルの結合キーを書くものだと
勝手に思い込んでいました。
(そこに日付条件を書くことを思いつきもしなかった)

一応JOINを使うということが間違っていなかっただけでも救いではありましたw

初心者的なことではありましたが、大変に理解が深まりました。
また質問させていただくと思いますが、よろしくお願いいたします。
OakBow
ベテラン
会議室デビュー日: 2007/09/15
投稿数: 51
投稿日時: 2007-09-15 11:30
関連する話題として、このあたりも読んでおくと理解が深まるかもしれません。
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=41031&forum=26&8

このスレッドで言及されているKBもあわせて読んでおきましょう。
http://support.microsoft.com/kb/176480/ja
話の内容はMSSQLかどうかに関係なく、SQL全般に通用する知識。

>(そこに日付条件を書くことを思いつきもしなかった)
私もそうでした。
昔はできないと思ってアプリ側でやりくりしてたんですが、こういうのって無駄に複雑で読みにくいコードになりやすいんですよね。
SQL一発でできた方がたいてい高速でコードもすっきりすると思いますけれど。
landy
会議室デビュー日: 2007/09/14
投稿数: 12
お住まい・勤務地: 中部
投稿日時: 2007-09-15 12:41
ひでぽん様

参考のリンク、読ませていただきました。
目から鱗的な部分もありましたので大変に参考になりました。

実の所は結果は出ていたので、1回回してIDと名前を表示後、もう一度表を上から読んで
対応するIDの当日メッセージを取り出すやり方で気にしていなかったのですが、
納品先の社内トラフィックが恐ろしく悪く、サーバにアクセスする回数を
極力減らす必要が出た為、今回のことを考えたわけでした。

ちょっとしたことでしたが大変勉強になりました。

みなさん、本当にありがとうございました。
1

スキルアップ/キャリアアップ(JOB@IT)