質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

4回答

3699閲覧

MySQLで重複しないレコードのみを抽出するSQLが遅い

mks

総合スコア80

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

1グッド

3クリップ

投稿2018/12/14 03:00

編集2018/12/14 03:06

開発中のシステムで、各顧客からの受注をデータベースで管理しているのですが、受注に付随する情報として「伝票番号」があり、この伝票番号が他の受注と重複していない受注のみを一覧表示する必要があります。

伝票番号は他社システムより振り出されるものですが、一定範囲の連番がサイクリックに振り出されるようで、そのため重複の条件として、伝票日付が前後3か月以内の受注のみを対象とすることになっています。

伝票番号は受注によって付与されないケースも、また、1つの受注に2件以上付与されるケースもありますが、最大2件管理することになっています。

あれこれ検索のSQLやインデックスをこね回してみても、受注データが3000件弱で4秒ほどかかってしまっており苦戦しております。
検索のSQLやインデックスの貼り方、あるいはテーブル構造の見直しでも何らかヒントが頂けたらと思っています。
MySQLのバージョンは5.6.42です。

テーブル構造

必要なところを抜き出すとこんな感じです。

SQL

1DROP TABLE IF EXISTS orders; 2CREATE TABLE orders( 3 id INT NOT NULL AUTO_INCREMENT COMMENT '伝票ID', 4 customer_id INT NOT NULL COMMENT '顧客ID', 5 voucher_date DATE NOT NULL COMMENT '伝票日付', 6 voucher_no1 VARCHAR(20) COMMENT '伝票番号1', 7 voucher_no2 VARCHAR(20) COMMENT '伝票番号2', 8 is_deleted TINYINT NOT NULL DEFAULT 0 COMMENT '削除フラグ(1:削除済み)', 9 PRIMARY KEY (id), 10 INDEX idx_orders_c_deleted(is_deleted, customer_id, voucher_no1, voucher_no2), 11 INDEX idx_orders_c_voucher_no1(customer_id, is_deleted, voucher_no1, voucher_date), 12 INDEX idx_orders_c_voucher_no2(customer_id, is_deleted, voucher_no2, voucher_date) 13) DEFAULT CHARSET=utf8;

試したこと

以下のようなSQLを書いてみましたが、EXPLAINの結果ordersのtypeがALLになってしまい、4秒近くかかります。また、ordersにFORCE INDEXを追加するとtypeはrefになるものの、時間はあまり変わりません。

SQL

1SELECT orders.* FROM orders 2WHERE is_deleted = 0 3AND customer_id = 2 4AND NOT EXISTS( 5 SELECT 1 FROM orders duplicated 6 WHERE 2 = duplicated.customer_id 7 AND duplicated.is_deleted = 0 8 AND orders.voucher_date - INTERVAL 3 MONTH <= duplicated.voucher_date 9 AND duplicated.voucher_date <= orders.voucher_date + INTERVAL 3 MONTH 10 AND orders.id != duplicated.id 11 AND ( 12 orders.voucher_no1 = duplicated.voucher_no1 13 OR 14 orders.voucher_no1 = duplicated.voucher_no2 15 OR 16 orders.voucher_no2 = duplicated.voucher_no1 17 OR 18 orders.voucher_no2 = duplicated.voucher_no2 19 ) 20);

以下も試しましたがref_or_nullになってもっと遅いです。(3000件弱で5秒ちょっと)

SQL

1SELECT orders.* FROM orders FORCE INDEX(idx_orders_c_deleted) 2WHERE customer_id = 2 3AND is_deleted = 0 4AND ( 5 orders.voucher_no1 IS NULL OR ( 6 orders.voucher_no1 NOT IN ( 7 SELECT duplicate1.voucher_no1 8 FROM orders duplicate1 9 WHERE duplicate1.customer_id = 2 10 AND duplicate1.is_deleted = 0 11 AND duplicate1.id != orders.id 12 AND duplicate1.voucher_no1 IS NOT NULL 13 AND duplicate1.voucher_date BETWEEN orders.voucher_date - INTERVAL 3 MONTH AND orders.voucher_date + INTERVAL 3 MONTH 14 ) 15 AND orders.voucher_no1 NOT IN ( 16 SELECT duplicate2.voucher_no2 17 FROM orders duplicate2 18 WHERE duplicate2.customer_id = 2 19 AND duplicate2.is_deleted = 0 20 AND duplicate2.id != orders.id 21 AND duplicate2.voucher_no2 IS NOT NULL 22 AND duplicate2.voucher_date BETWEEN orders.voucher_date - INTERVAL 3 MONTH AND orders.voucher_date + INTERVAL 3 MONTH 23 ) 24 ) 25 OR 26 orders.voucher_no2 IS NULL OR ( 27 orders.voucher_no2 NOT IN ( 28 SELECT duplicate3.voucher_no1 29 FROM orders duplicate3 30 WHERE duplicate3.customer_id = 2 31 AND duplicate3.is_deleted = 0 32 AND duplicate3.id != orders.id 33 AND duplicate3.voucher_no1 IS NOT NULL 34 AND duplicate3.voucher_date BETWEEN orders.voucher_date - INTERVAL 3 MONTH AND orders.voucher_date + INTERVAL 3 MONTH 35 ) 36 OR 37 orders.voucher_no2 NOT IN ( 38 SELECT duplicate4.voucher_no2 39 FROM orders duplicate4 40 WHERE duplicate4.customer_id = 2 41 AND duplicate4.is_deleted = 0 42 AND duplicate4.id != orders.id 43 AND duplicate4.voucher_no2 IS NOT NULL 44 AND duplicate4.voucher_date BETWEEN orders.voucher_date - INTERVAL 3 MONTH AND orders.voucher_date + INTERVAL 3 MONTH 45 ) 46 ) 47);

よろしくお願い致します。

takotakot👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

voucher_no1, voucher_no2,IDを共に含むインデックスが無いですね。
効率から考えると、以下の様な並びのインデックスじゃないかな。
(customer_id, voucher_date, voucher_no1, voucher_no2, ID, is_deleted)

チューニングは適切にインデックスが使用される所から徐々に条件を追加するなどすると、分かりやすいですよ。

追記

SQLは解決したとして、インデックスについて纏めると
メイン用のインデックス(customer_id, voucher_date, voucher_no1, voucher_no2, is_deleted)
サブクエリー用のインデックス1(customer_id, voucher_date, voucher_no1)
サブクエリー用のインデックス2(customer_id, voucher_date, voucher_no2)
になるかと。
is_deletedidについてはフィルター程度でしょうから、インデックスが使われない様なら、インデックスに含めるという事で。

現状とあまり違いは無いかもしれませんが、順序を変えるのは効果が出るかもしれません。
狙いとしては、抽出条件がインデックスのみでの解決となる事。

投稿2018/12/14 03:22

編集2018/12/19 00:52
sazi

総合スコア25138

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mks

2018/12/14 03:41 編集

ありがとうございます。 以下をそれぞれ試してみました。 (customer_id, voucher_date, voucher_no1, voucher_no2, is_deleted) (customer_id, voucher_no1, voucher_no2, voucher_date, is_deleted) (customer_id, voucher_no1, voucher_no2, is_deleted, voucher_date) そのままではインデックス使用されないので、FORCE INDEXあり、なし両方試してみたのですが、所要時間は変わりませんでした。SQL自体の見直しをすべきですかね。
sazi

2018/12/14 04:14

WHERE 2 = duplicated.customer_id を WHERE order.customer_id = duplicated.customer_id としたら変化はありますか?
sazi

2018/12/14 04:16

多分、voucher_noとIDがネックだと思うんですよね。
mks

2018/12/14 04:21

度々ご回答ありがとうございます。 ご提案のように変更するとサブクエリで最初に提案頂いたINDEXが使用されるようになりましたが、レスポンスは10秒近くかかるようになりました。 (ちなみに、元のSQLで左辺に2が来ているのは、もともとご提示の通りだったためでした)
sazi

2018/12/14 04:36 編集

以下ではどのような状況になりますか? SELECT orders.* FROM orders WHERE is_deleted = 0 AND customer_id = 2 AND NOT EXISTS( SELECT 1 FROM orders duplicated WHERE 2 = duplicated.customer_id AND duplicated.is_deleted = 0 AND orders.voucher_date - INTERVAL 3 MONTH <= duplicated.voucher_date AND duplicated.voucher_date <= orders.voucher_date + INTERVAL 3 MONTH AND orders.id != duplicated.id AND orders.voucher_no1 = duplicated.voucher_no1 )
mks

2018/12/14 04:51

ありがとうございます。伝票番号1のみということですよね。 先ほどssasakiの回答を受けて試してみたら0.01秒前後で結果が返ってきたので、NOT EXISTSを4つANDでつなげばいいのではないかと今思い至ったところです。 それだと0.1秒弱で戻ってきます。
sazi

2018/12/14 04:53

そうです。 冗長ですけど、そういった記述になります。
sazi

2018/12/14 04:58

(voucher_no1, voucher_no2)の組み合わせをインデックスで表現できないので、それぞれで問い合わせる形を取るしかないという事ですね。
mks

2018/12/14 05:06

インデックスが木構造であることを思い出すとなるほどという感じです。 ありがとうございました。以下で解決と致します。 SELECT orders.* FROM orders WHERE is_deleted = 0 AND customer_id = 2 AND NOT EXISTS( SELECT 1 FROM orders duplicated WHERE 2 = duplicated.customer_id AND duplicated.is_deleted = 0 AND orders.id != duplicated.id AND orders.voucher_no1 = duplicated.voucher_no1 AND orders.voucher_date - INTERVAL 3 MONTH <= duplicated.voucher_date AND duplicated.voucher_date <= orders.voucher_date + INTERVAL 3 MONTH ) AND NOT EXISTS( SELECT 1 FROM orders duplicated WHERE 2 = duplicated.customer_id AND duplicated.is_deleted = 0 AND orders.id != duplicated.id AND orders.voucher_no1 = duplicated.voucher_no2 AND orders.voucher_date - INTERVAL 3 MONTH <= duplicated.voucher_date AND duplicated.voucher_date <= orders.voucher_date + INTERVAL 3 MONTH ) AND NOT EXISTS( SELECT 1 FROM orders duplicated WHERE 2 = duplicated.customer_id AND duplicated.is_deleted = 0 AND orders.id != duplicated.id AND orders.voucher_no2 = duplicated.voucher_no1 AND orders.voucher_date - INTERVAL 3 MONTH <= duplicated.voucher_date AND duplicated.voucher_date <= orders.voucher_date + INTERVAL 3 MONTH ) AND NOT EXISTS( SELECT 1 FROM orders duplicated WHERE 2 = duplicated.customer_id AND duplicated.is_deleted = 0 AND orders.id != duplicated.id AND orders.voucher_no2 = duplicated.voucher_no2 AND orders.voucher_date - INTERVAL 3 MONTH <= duplicated.voucher_date AND duplicated.voucher_date <= orders.voucher_date + INTERVAL 3 MONTH );
mks

2018/12/14 05:23 編集

INDEXですけど、このSQLだと日付の絞り込みにはINDEX使われないので、伝票番号より後ろがよさそうです。 (実際、日付を伝票番号より前に持ってくると10秒以上かかってしまいます) is_deletedは、type=Using indexを期待するために含めてもいいかもですが、現状、なくてもあまり変わりませんでした。 なので、 メイン用のインデックス(customer_id, voucher_no1, voucher_no2, voucher_date) サブクエリー用のインデックス1(customer_id, voucher_no1, voucher_date) サブクエリー用のインデックス2(customer_id, voucher_no2, voucher_date)
sazi

2018/12/14 05:20

頻繁に更新してしまいました。良ければ確認してみて下さい。
sazi

2018/12/14 05:27 編集

相関でメインより取り出した項目を、サブクエリーで使用しますから、日付もインデックス対象です。 ですので、サブクエリーでは、サブクエリー側の項目は式にしないこと (そうなっているようですけど) 順番で変化があるのは分布によるものですね。
sazi

2018/12/14 05:25

WHERE 2 = duplicated.customer_idは、相関にすると遅くなりますか?
mks

2018/12/14 05:33 編集

サブクエリ側を WHERE orders.customer_id = duplicated.customer_id としても所要時間は定数値の場合と同じですね。 > サブクエリーでは、サブクエリー側の項目は式にしないこと 式にしない、とは計算したり関数を通したりしない、という意味でよかったでしょうか? orders.voucher_date - INTERVAL 3 MONTH <= duplicated.voucher_date だとメインクエリ側は3か月ひいてるけどサブクエリ側はそのままの値だからOKということでしょうか?
mks

2018/12/14 05:46

式インデックスは初めて知りました。勉強不足でした。 MySQLのバージョンを変更しないと使えませんが、レコードを増やしてみてから検討します。 いろいろありがとうございます。勉強になりました。
guest

0

SQL

1AND orders.voucher_date - INTERVAL 3 MONTH <= duplicated.voucher_date 2AND duplicated.voucher_date <= orders.voucher_date + INTERVAL 3 MONTH

これを where 句の末尾に移動したら時間が変わるなんてことはないですかね?
この部分はINDEXは効かないし、時間がかかる可能性があると思うので。
基本こういったものはオプティマイザーの方で最適化されているはずですが、経験上うまく働かないこともあったので、念のため最適と思われる順序を試してみるのも良いと思います。

あとは、以下のように条件を絞ってコストが高い部分を見極めてみるのも1つの手がかりになると思います。

・「前後3か月以内」という条件を抜かすと速くなったりしますか?
・「伝票番号1」「伝票番号2」という条件を「伝票番号1」のみとした場合、速くなったりしますか?

投稿2018/12/14 04:20

ssasaki

総合スコア1167

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mks

2018/12/14 04:34

いろいろありがとうございます。 日付の条件をサブクエリの末尾にしてもレスポンスは変わりませんね。 ちなみに、試したこととして明記はしなかったのですが、順番の変更はすべて試してみましたが、変化しなかったです。 前後3か月を条件からはずすと、13秒とさらに遅くなりました。試しにvoucher_dateを含まないINDEXを追加して試してもみたのですが変わりません。 伝票番号1=伝票番号1のみにした場合は0.01秒前後です。ネックになっているのはやはりその部分のようです。
mks

2018/12/14 04:56 編集

ありがとうございます。「伝票番号1のみにする」がヒントになりました。NOT EXISTSをANDで4つつなぐのでよさそうです。
ssasaki

2018/12/14 05:40

なるほど。OR検索がネックだったようですね
guest

0

解決済みのようですが

SQL

1 orders.voucher_no1 = duplicated.voucher_no1 2 OR 3 orders.voucher_no1 = duplicated.voucher_no2

SQL

1 orders.voucher_no1 IN(duplicated.voucher_no1, duplicated.voucher_no2)

と表記できるはずです。もしうまくいって時間が変わらないのであれば、冗長な記述は少し減らせますね。

案1

SQL

1SELECT orders.* FROM orders 2 WHERE is_deleted = 0 3 AND customer_id = 2 4 AND NOT EXISTS( 5 SELECT 1 FROM orders duplicated 6 WHERE 2 = duplicated.customer_id 7 AND duplicated.is_deleted = 0 8 AND orders.id != duplicated.id 9 AND orders.voucher_no1 IN(duplicated.voucher_no1, duplicated.voucher_no2) 10 AND orders.voucher_date - INTERVAL 3 MONTH <= duplicated.voucher_date 11 AND duplicated.voucher_date <= orders.voucher_date + INTERVAL 3 MONTH 12 ) 13 AND NOT EXISTS( 14 SELECT 1 FROM orders duplicated 15 WHERE 2 = duplicated.customer_id 16 AND duplicated.is_deleted = 0 17 AND orders.id != duplicated.id 18 AND orders.voucher_no2 IN(duplicated.voucher_no1, duplicated.voucher_no2) 19 AND orders.voucher_date - INTERVAL 3 MONTH <= duplicated.voucher_date 20 AND duplicated.voucher_date <= orders.voucher_date + INTERVAL 3 MONTH 21 ) 22;

案2

SQL

1SELECT orders.* FROM orders 2 WHERE is_deleted = 0 3 AND customer_id = 2 4 AND NOT EXISTS( 5 SELECT 1 FROM orders duplicated 6 WHERE 2 = duplicated.customer_id 7 AND duplicated.is_deleted = 0 8 AND orders.id != duplicated.id 9 AND duplicated.voucher_no1 IN(orders.voucher_no1, orders.voucher_no2) 10 AND orders.voucher_date - INTERVAL 3 MONTH <= duplicated.voucher_date 11 AND duplicated.voucher_date <= orders.voucher_date + INTERVAL 3 MONTH 12 ) 13 AND NOT EXISTS( 14 SELECT 1 FROM orders duplicated 15 WHERE 2 = duplicated.customer_id 16 AND duplicated.is_deleted = 0 17 AND orders.id != duplicated.id 18 AND duplicated.voucher_no2 IN(orders.voucher_no1, orders.voucher_no2) 19 AND orders.voucher_date - INTERVAL 3 MONTH <= duplicated.voucher_date 20 AND duplicated.voucher_date <= orders.voucher_date + INTERVAL 3 MONTH 21 ) 22;

投稿2018/12/18 00:15

編集2018/12/18 05:17
takotakot

総合スコア1111

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mks

2018/12/18 02:26

回答ありがとうございます。 結局のところ、OR自体がオーバーヘッドになっていたようですので、サブクエリ部分を以下のように置き換えることで速度改善しました。 AND NOT EXISTS(orders.voucher_no1と等しいvoucher_no1を持つレコード) AND NOT EXISTS(orders.voucher_no1と等しいvoucher_no2を持つレコード) AND NOT EXISTS(orders.voucher_no2と等しいvoucher_no1を持つレコード) AND NOT EXISTS(orders.voucher_no2と等しいvoucher_no2を持つレコード) これ以上ないくらい冗長になりましたが、検索・結合するテーブル1個ごとに1つしかINDEXを使用できないことを考えると仕方ないのかと。 ご提案のINを用いる方法だと20秒近くかかってしまいますので、やはり複数の値を検索してORを取るのは得策ではないのだと思います。
takotakot

2018/12/18 03:31 編集

はい、他の方の回答やコメントは全て拝見しております。 その状態でも、 「voucher_no1 または voucher_no2 が orders.voucher_no1と等しい持つレコードを抽出」 することが、IN 句でできますので、工夫の余地があると考えてコメントしました。 1. orders.voucher_no1 IN (voucher_no1, voucher_no2) orders.voucher_no2 IN (voucher_no1, voucher_no2) 2. voucher_no1 IN (orders.voucher_no1, orders.voucher_no2) voucher_no2 IN (orders.voucher_no1, orders.voucher_no2) どちらも文法的には正しいクエリのはずですので、少しだけ短くかける可能性があります。
mks

2018/12/18 04:43 編集

速度改善とは関係なく、短くできる方法のご提案ということでしたでしょうか? 残念ながら、サブクエリ内でOR条件(INを使っても意味合い的にはOR検索と同じですよね)を使うこと自体が、うまくインデックスが使えず速度が落ちてしまうようです。 ※何度も編集してすみません、ご提案頂けること自体はありがたく思っております。
takotakot

2018/12/18 05:12

もう少しきちんと書くべきでしたね。 短くできる方法の提案かつ、オプティマイザが賢ければ、インデックスを使ってくれる可能性はあります。 今回は「賢くないから遅い」という状態のため、良くならない可能性もあります。 具体的には、4つの場合分けとなっていますが、2つの場合分けにできる可能性があります。 IN は OR 検索と意味合いは同じなのですが、カラムの記述が1回だけになりますので、インデックスを用いてくれる可能性があるわけですね。 OR が4つ並んでいる場合ではダメでも、voucher_no1 片方だけならインデックスを使ってくれる可能性があって…というところですね。回答を少し追記しておきます。
mks

2018/12/18 05:51

ORでつなぐと遅い原因は、検索・結合するテーブル1個ごとに1つしかINDEXを使用できないせいで、サブクエリ側を検索する際にvoucher_no1の方はインデックスを使えても、voucher_no2は、voucher_no1を検索した同じインデックスを使わざるを得ず、結局customer_idで絞り込んだ結果を総なめにするような動作になってしまっているせいではないかと思っています。 ただ、それなら以下のように2つに分けたらそれなりにパフォーマンス出そうな気もするんですが、やはり19秒と、ORを4つつなぐより遅い結果になってしまいました。 AND NOT EXISTS( SELECT 1 FROM orders duplicated WHERE 2 = duplicated.customer_id AND duplicated.is_deleted = 0 AND orders.voucher_date - INTERVAL 3 MONTH <= duplicated.voucher_date AND duplicated.voucher_date <= orders.voucher_date + INTERVAL 3 MONTH AND orders.id != duplicated.id AND duplicated.voucher_no1 IN (orders.voucher_no1, orders.voucher_no2) ) AND NOT EXISTS( SELECT 1 FROM orders duplicated WHERE 2 = duplicated.customer_id AND duplicated.is_deleted = 0 AND orders.voucher_date - INTERVAL 3 MONTH <= duplicated.voucher_date AND duplicated.voucher_date <= orders.voucher_date + INTERVAL 3 MONTH AND orders.id != duplicated.id AND duplicated.voucher_no2 IN (orders.voucher_no1, orders.voucher_no2) ); 上記の分け方でINをORに置き換えても、やはり18秒かかりますね。
takotakot

2018/12/18 06:18

ありがとうございます。 AND duplicated.voucher_no1 IN (orders.voucher_no1, orders.voucher_no2) AND duplicated.voucher_no2 IN (orders.voucher_no1, orders.voucher_no2) を AND orders.voucher_no1 IN (duplicated.voucher_no1, duplicated.voucher_no2) AND orders.voucher_no2 IN (duplicated.voucher_no1, duplicated.voucher_no2) ならうまくいく可能性もありますが、のぞみは薄そうですね。難しいですね。 SHOW PROFILE も参考にしてみてください。 https://teratail.com/questions/43797
mks

2018/12/18 06:39 編集

AND orders.voucher_no1 IN (duplicated.voucher_no1, duplicated.voucher_no2) AND orders.voucher_no2 IN (duplicated.voucher_no1, duplicated.voucher_no2) 先ほど書きましたが、こちらも20秒近くかかります。オプティマイザが賢くない(選ばれるインデックスが適切でない)というよりはMySQLの仕様ではないのでしょうか。 > SHOW PROFILE も参考にしてみてください。 どの過程で時間がかかっているか見るという意味でしょうか?
takotakot

2018/12/18 06:50

> 先ほど書きました 失礼しました、見落としをしていたようですね。 そうですね。オプティマイザが賢くない場合は、INDEX 指定が効く可能性もありますが、これはもう議論がある程度されているようなので口を挟みません。クエリを分割する以外に、2つ以上のインデックスを使ってくれないということなのでしょう。 > どの過程で時間がかかっているか見るという意味でしょうか? はい、そうです。今回は役に立たない気もします。
mks

2018/12/18 07:00

> クエリを分割する以外に、2つ以上のインデックスを使ってくれないということなのでしょう。 ORでつながれた各条件が、同じカラムに対する条件なら問題ないのでしょうが、別のカラムの場合はそのうちの1つしかインデックスの効果を期待できないということなのだと思います。確認していないのですが、単純に伝票番号1または2が'12345'であるレコードを抽出する場合も、別々にSELECTした結果をUNIONする方が速かったりするのかもしれません。勉強になりました。 >> どの過程で時間がかかっているか見るという意味でしょうか? > はい、そうです。今回は役に立たない気もします。 覚えておきます。といってももう廃止予定の構文なんですね。
guest

0

MYSQLは詳しくないので、間違っているかもしれませんが

SQL

1AND NOT EXISTS( 2 SELECT 1 FROM orders duplicated

上記のEXISTS 内の FROM に orders がありますが
これは先頭の orders と同じ扱いになるんですかね?

この、EXISTS 内の FROM には orders は要らないような気がします。
私の認識が間違ってたらすいません。

投稿2018/12/14 04:32

trick

総合スコア366

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mks

2018/12/14 04:38

EXISTS内では、ordersテーブル内に同じ伝票番号がないかを検索しているため、FROM ordersで正しいと思います。duplicatedはサブクエリ内のordersテーブルの別名です。相関サブクエリであり、メインのクエリと同じテーブル名なので、別名をつける必要があると思います。 (私もSQLは得意ではないので誤っていたらすみません)
trick

2018/12/14 04:40

なるほど別名ですね、私が間違っていました。 申し訳ありません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問