• 締切済み

NOT INをNOT EXISTSで書き直したい

こんにちは。SQLでNOT INが実行速度が遅いため、EXISTSで書き直したいのですが、思っている結果がでません。 SQLのどこが間違っているかお教え頂けませんでしょうか? ■ ・テーブル名:R_TABLE ・フィールド:id データ: id(ユニークではない) 001 002 003 003 003 007 008 009 ■ ・テーブル名:P_Master ・フィールド:id データ: id(ユニーク) 001 002 003 ■やりたい事 R_TABLEのデータを条件によって削除したい。 条件はP_MASTERに無いR_TABLEの行を削除したいです。 ■欲しい結果 R_TABLE 001 002 003 003 003 ■書いたSQL DELETE FROM R_TABLE WHERE R_TABLE.id NOT IN (SELECT R_TABLE.id FROM R_TABLE INNER JOIN P_MASTER ON R_TABLE.id = P_MASTER.id) これは正しい結果がでました。 書きなおしたSQL DELETE FROM R_TABLE WHERE R_TABLE.id WHERE NOT EXISTS (SELECT R_TABLE.id FROM R_TABLE INNER JOIN P_MASTER ON R_TABLE.id = P_MASTER.id) 結果はR_TABLEから何も消されていませんでした。 どこを修正すれば正しい結果が得られるでしょうか? 副問い合わせで、R_TABLEとP_MASTERのINNER JOINの結果が得られ、R_TABLEからINNER JOINに含まれないデータ削除しろという命令だと思っていたのですが違うみたいです。 どこを修正すればよろしいでしょうか? よろしくお願いします。

  • MySQL
  • 回答数3
  • ありがとう数11

みんなの回答

  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.3

こんな感じでよくない? DELETE R_TABLE FROM R_TABLE LEFT JOIN P_Master using(id) WHERE P_Master.id IS NULL

  • mpro-gram
  • ベストアンサー率74% (170/228)
回答No.2

not exists () は内部のサブクエリで1行もデータ取得でき無い時にのみtrue です。 NOT IN で記述のサブクエリは、何行かのデータが有るはずなので、同じサブクエリをいれただけだと全部false(削除されない)になってしまうのは必然です。 しかし、mysqlでは、delete,update,insert のときには、サブクエリのfrom節に、編集対象テーブルを指定できないエラーがでると思うのですが、使ってるデータベースシステムは何ですか?SQLiteあたりだとエラーにならないようですが。 とりあえず、not exists ()を使うときには、外側クエリにおける各行のカラム値と比較するのが普通なので相関サブクエリとなります。以下はmysqlでも実行可能 DELETE FROM `R_TABLE` WHERE NOT EXISTS (SELECT id FROM `P_MASTER` where R_TABLE.id = P_MASTER.id) ;

  • Siegrune
  • ベストアンサー率35% (316/895)
回答No.1

DELETE FROM R_TABLE WHERE R_TABLE.id WHERE NOT EXISTS (SELECT R_TABLE.id FROM R_TABLE INNER JOIN P_MASTER ON R_TABLE.id = P_MASTER.id) って「WHERE R_TABLE.id WHERE」のところでエラーにならなかったですか? (MySQLはエラーにならないのかなあ?) DELETE FROM R_TABLE AS x1 WHERE NOT EXISTS (SELECT R_TABLE.id FROM R_TABLE AS x2 INNER JOIN P_MASTER ON x2.R_TABLE.id = P_MASTER.id AND x1.R_TABLE.id = x2.R_TABLE.id) といった感じでうまくいくのでは?(MySQLがないので未検証ですが。)

関連するQ&A

  • INNER JOIN > EXISTS > IN

    SQL Server 2008での話です。 製品テーブルと、その製品の売れ行きのランキングデータを格納するテーブルがあって、 売れ行きの良いものTOP10だけ取り出したいと思っています。 製品IDがキーになっています。 ランクテーブルから10位以内の製品IDをSELECTし、それをIN句に 入れるということをやっていたのですが、遅かったので、EXISTSに 書き変えました。 更に、INNER JOINにしてしまえば、WHERE句より実行されるので、 より速くなると聞き、試しているところです。 実際、速くはなったのですが、以下パターンだとそれほど差が出ません。 (データの件数のせいだとは思いますが…) どちらがベターなのでしょうか。 Bのほうが先に絞り込みをしてから結合されるから、速い…ような気が しているのですが、動き的には一緒だったりしますかね…。 もしより良い書き方がありましたらご教授ください。 ■Aパターン SELECT * FROM 製品テーブル INNER JOIN ランクテーブル ON 製品テーブル.製品ID = ランクテーブル.製品ID AND ランクテーブル.順位 <= 10 ■Bパターン SELECT * FROM 製品テーブル INNER JOIN ( SELECT ランクテーブル.製品ID FROM ランクテーブル WHERE ランクテーブル.順位 <= 10 ) TMP ON TMP.製品ID = 製品テーブル.製品ID

  • 差集合について

    MYSQL5.5について質問です。 Table1.idからTable2.idを引いて差集合を得たいとと思います。 例えば、 Table1.id 001 002 003 004 Tbale2.id 002 003 004 とあれば、最終的に欲しい結果は 001 のみです。 SQLを書くと下記のようなSQLになると思います。 mysql> SELECT table1.* FROM table1 -> LEFT JOIN table2 ON table1.id=table2.id -> WHERE table2.id IS NULL; しかし、これで差集合が得られるのかわかりません。 left joinして、table2 is nullにすれば、差集合に なるか教えて頂けますでしょうか? また、not existsで代用できるみたいですが、その場合、 どのようなSQLを書けばよいでしょうか?

  • distinct をexistsに変換する

    distinctをexistsに変換した方がパフォーマンスが良いようで、 例えば以下の例があるとします ---------------------------------- (前)SELECT DISTINCT a.ID1, a.NAME1 FROM TABLE1 a, TABLE2 b WHERE a.ID1 = b.ID2 (後)SELECT a.ID1, a.NAME1 FROM TABLE1 a    WHERE EXISTS ( SELECT 'X' FROM TABLE2 b WHERE a.ID1 = b.ID2) ---------------------------------- もっと複雑なSQLの場合、EXISTSに変換できるのでしょうか?。複雑なSQLとは、 「複数のテーブルからカラムを取得」「テーブル結合が2つ以上」「外部結合」 などのSQLで、以下に例を示します。 (例)SELECT DISTINCT a.ID1,a.NAME1,b.ID2,b.NAME2,c.ID3,c.NAME3    FROM TABLE1 a,TABLE2 b,TABLE3 c    WHERE a.ID1 = b.ID1(+)      AND a.ID1 = c.ID1(+)

  • inner joinについて

    SQLのデータ抽出方法についてお教え下さい。 TABLE_2をdistinctで重複を無くして、TABLE_1とinner joinさせたいです。 select distinct TABLE_2.id と select TABLE_1.ID from TABLE_1 inner join distinct TABLE_2.ID といったようなことをやりたいです。 TABLE_1 ID 001 001 002 002 002 TABLE_2 ID 001 001 002 002 002 環境はMYSQL5.5になります。よろしくお願いいたします。

  • inner joinでサブクエリ

    SQLについてお教え頂けませんでしょうか? 在庫テーブル ・ID ・数量 データ 001,1 001,3 002,3 002,2 002,4 003,2 商品テーブル ・ID データ 001 002 003 004 やりたいこと: 在庫テーブルには重複しているIDがあります。 商品テーブルには重複しているIDはありません。 在庫テーブルの重複を削除したIDと商品テーブルのIDをinner joinで結びたいと思います。 ・select distinct ID FROM 在庫テーブル ・select ID FROM 商品テーブル この2つのjoin方法がわかりません。 結果として、 001 002 003 を取得したいいです。宜しくお願いします。 ちなみに select ID from 商品テーブル inner join 在庫テーブル 商品テーブル.ID = exists(select distinct ID from 在庫テーブル) というコードを書きましたが、動きませんでした・・・抽出データが0件でした・・・

  • inner joinをすると数がおかしくなります

    SQLのinner joinについてお教え下さい。環境はWin 7 MYQL5です。 t1テーブルのデータ ID,在庫 001,22 t2テーブルのデータ ID,出庫 001,17 001,3 SELECT Sum(t1.stock) AS `在庫` FROM t1 where id = '001' 上記SQLの結果は22と表示されます。 SELECT Sum(t1.stock) AS `在庫` FROM t1 INNER JOIN t2 on t1.id = t2.id where id = '001' とやると、結果が44になってしまいます。 なぜそんな結果になってしまうのでしょうか? 結果はt1.stockは在庫22なので、22と表示するようにしたいです。 よろしくお願いいたします。

    • ベストアンサー
    • MySQL
  • Not Exists の絞込みについて

    SQLServer2005 Express にて次のようなSQLをVB.NET2005で発行しようとしたらうまくいきません SELECT CustomerID,CustomerName FROM T_Customer WHERE Kana LIKE N'カ%' OR Kana LIKE N'キ%' OR Kana LIKE N'ク%' OR Kana LIKE N'ケ%' OR Kana LIKE N'コ%' AND not exists(select 1 from T_ABC where T_Customer.CustomerID=T_ABC.CustomerID 目的はT_ABCテーブルにあるデータ以外のデータの中からカ行のKana読みの データのみを抽出するものです SQL初学者でお恥ずかしい限りですがよろしくご教授ください

  • SQLiteでIF NOT EXISTSの使い方

    my $dbh = DBI->connect("dbi:SQLite:dbname=$filename","",""); で ' CREATE TABLE "sampleTable1" (' # ' CREATE TABLE IF NOT EXISTS "sampleTable1" (' .'"samplekey1" INTEGER, "samplekey2" INTEGER' .' ); ' だと問題ないのですが、 コメント部分ので 生成しようとすると IF NOT EXISTS をだと NOTのまえがどうのこうのと エラーになるので IF NOT EXISTS は 使えないのでしょうか? SQLiteでIF NOT EXISTSのような使い方がわからないので 接続後に my @names = $dbh->tables; $Miteigi_data = 1; for my $name (@names) { #  テーブル名比較 if ( ($name eq 'sampleTable1') || ($name eq '"sampleTable1"') ) { $Miteigi_data = 0; } } で  テーブル名を確認して あるかないのか変数に代入して置いて  あとから条件文で if ($Miteigi_data) 上のテーブルの生成を行うことにして回避したのですが dbi:SQLiteで TABLE IF NOT が使えるようにするにはどうしたらいいのでしょうか

    • ベストアンサー
    • Perl
  • PL/SQLのDELETE文について

    PL/SQLでDELETE文を書こうとしているのですが、 文法がわかりません。。。 分かる方がおられましたら、教えてくださいm(_ _)m 今、TABLE1を削除したいのですが、条件がいろいろあって、 以下のように書いてみたのですがダメでした。 こういう書き方は、できないんでしょうか・・・。 削除条件は、TABLE2に存在し、かつ、TABLE2のTENSUが0のもので、 TABLE3が存在しないものです。 DELETE TABLE1 FROM TABLE1 ,TABLE2 ,TABLE3 WHERE TABLE1.ID = TABLE2.ID AND TABLE2.TENSU = 0 AND Not Exists (SELECT TABLE3.ID FROM TABLE3 WHERE TABLE3.ID = TABLE2.ID) 説明が下手なので、うまく、伝わっているか、心配なのですが・・・、 よろしくお願いします。

  • mySQLの内部結合について

    現在mySQLを使って、SQL文の勉強をしているのですがわからないことがあり、質問させていただきました。 テーブル同士をINNER JOINして結果を取得して、これに対してさらに別の処理(Whereなど)を行いたいのですが、うまくやり方がわかりません。 具体的にSQL文でいうとこんな感じです(ただしエラーが出て動きません)。 SELECT cmaster.comic_id,tags,title FROM mysql.comic_tag as ctag INNER JOIN mysql.comicmaster as cmaster ON ctag.comic_id = cmaster.comic_id AND WHERE tags = 'aa' この処理でやりたいことを説明するとcomic_tagとcomicmasterを結合して、その結果に対してさらにWhereでデータを絞るということしています。 このような場合はどのように処理をしたらいいんでしょうか?またjoinした後のデータを、既存のテーブルのように扱いたいのですが、なにか方法はないのでしょうか?

    • ベストアンサー
    • MySQL