アプリ版:「スタンプのみでお礼する」機能のリリースについて

こんにちは。DELETE文の削除条件について教えてください。

例えば下記のような2つのテーブルがあったとします。

ATABLE
KEY1(ID) KEY2(DATE) ・・・・・・・・・・
------------------------------------------------
100000 2004/09/01 ・・・・・・・・・・
200000 2004/09/01 ・・・・・・・・・・
300000 2004/09/01 ・・・・・・・・・・

BTABLE
KEY1(ID) KEY2(DATE) CODE ・・・・・・・・・・
------------------------------------------------
100000 2004/09/01 0 ・・・・・・・・・・
200000 2004/09/01 0 ・・・・・・・・・・
300000 2004/09/01 1 ・・・・・・・・・・

この2つのテーブルで、BTABLEのCODEが1のレコードにKEYで関連付くATABLEのレコードを削除したいのです。

プログラムの中では対応できるのですが、SQL1文で実行させることはできるでしょうか?

とりあえず下記のように作ってみました(いたずらに長いかもしれませんが)。

DELETE FROM ATABLE WHERE

KEY1 IN (SELECT ATABLE.KEY1 FROM ATABLE,BTABLE WHERE ATABLE.KEY1 = BTABLE.KEY1 AND ATABLE.KEY2 = BTABLE.KEY2 AND BTABLE.CODE = 1) AND

KEY2 IN (SELECT ATABLE.KEY2 FROM ATABLE,BTABLE WHERE ATABLE.KEY1 = BTABLE.KEY1 AND ATABLE.KEY2 = BTABLE.KEY2 AND BTABLE.CODE = 1)

これで良い/悪い、もっと簡潔にできる、などありましたら是非お聞かせ願えますでしょうか?

よろしくお願いします。

A 回答 (4件)

 #3です。


 おそらく、私のsqlは、標準SQLをサポートする大概のdbmsで有効だと思います。リストの比較は、どうかしら・・・この文法をsql serverがサポートしているかどうかはちょっと知りません。

 ちなみに、元のh164さんのsqlですが、どうも違和感を感じるなと思ったら、やっぱり、まずいです。微妙な問題が潜んでいます。

atable
key1 key2  ・・・
--------------------------
10000 2004/09/01
10000 2004/09/02
20000 2004/09/01
20000 2004/09/02

btable
key1 key2 code
--------------------------
10000 2004/09/01 1
10000 2004/09/02 0
20000 2004/09/01 0
20000 2004/09/02 1

 というデータを考えたとき、おそらく、削除レコードは、10000,2004/09/01と20000,2004/09/02の二つのレコードだと思われるでしょうが・・・
 実は、全部のレコードが削除されます。
 たとえば、10000,2004/09/02のレコードですが、まず、第一の比較に置いて10000,2004/09/01が副select文の結果セットに存在するので、key1の条件は真です。第二の比較でも同様に、副select文の結果セットに20000,2004/09/02が存在するので、この条件も真となります。というわけで、本来削除されるはずのない、10000,2004/09/02のレコードは、削除されます。

 複数フィールドにおける比較を、各フィールドの比較のAND条件で結合する時は、よほど注意をしないとこういう事があります。ご注意を。

 #1および、#2の方の回答では、この問題は発生しません。リストとして同時に比較しているからです。
 #3の私のSQLも大丈夫なはずです。レコードの比較時に、元のDELETE対象の現在の操作行を連動させているからです。(従って、副SELCT文のFROM句にはATABLEの指定がありません。これは、誤記ではありませんのでご注意を。)
    • good
    • 0
この回答へのお礼

ありがとうございました。とても参考になりました。

お礼日時:2004/09/16 09:48

delete from atable a


where exist (select * from btable b
where a.key1=b.key1 and
a.key2=b.key2 and
b.code=1);
でいけそうな気がします。
今テストできないので自信なしとしておきます。

この回答への補足

回答を頂いた方々、どうもありがとうございます。

最初、私が書いた物より随分簡潔になりましたね。見易いです。

ちなみに、このSQLはSQL Serverでも動作しますでしょうか?(一応、両方の環境でやってみたいもので)

情報を小出しにしてしまい、申し訳ありません。

また、このカテゴリ(Oracle)にはあてはまらないかも知れませんが、よろしければご返答ください。

補足日時:2004/09/15 14:54
    • good
    • 0

DELETE FROM ATABLE WHERE


( KEY1, KEY2 ) IN (
 SELECT KEY1, KEY2
 FROM BTABLE
 WHERE CODE=1
)

動作チェックをしておりませんが、大丈夫だと思います。
    • good
    • 0
この回答へのお礼

本来ならポイントを発行差し上げたいのですが、回答No1のご回答のna_kirajp様よりほんの数分の差ですが遅いご回答でしたので、ポイントを2名様にしかつけられないこともあり、今回はポイントの発行はなしとさせて頂きます。
ですが、感謝の気持ちに変わりないということはご理解下さい。ありがとうございました。

お礼日時:2004/09/16 09:55

こんにちは



提示のSQLで基本的に考え方は合っているし問題ないと思いますが、他の例として

delete from ATABLE where (ATABLE,KEY1,ATABLE,KEY2)
in (select KEY1,KEY2 from BTABLE where code=1);

なんて言うのはどうでしょうか?
違いは、BTABLEを一度参照するだけでATABLEを消せるので
パフォーマンス的には多少良いかと・・・
    • good
    • 0
この回答へのお礼

ありがとうございました。
回答No2のGoF様と同内容のご回答でしたが、回答時間の関係でこちらにポイントを差し上げることにします

お礼日時:2004/09/16 09:55

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!