このようなサブクエリを使用する際の問題は、各サブクエリがフルテーブルをスキャンする必要があることです。また、FIND_IN_SET()を使用すると、索引を持っていても完全な表スキャンが強制されます。だからあなたは12回のフルテーブルスキャンをしています。
サブクエリをまったく使用しないソリューションです。それはテーブルをスキャンして一致するclientOrderId値を一度取得し、必要なtxTypesに一致するすべての行のスーパーセットを取得します。
次に、txnTypeが特定の型のいずれかである場合は、totalAmountの各合計が条件付きです。そうでない場合は、各行のtotalAmountにゼロを使用し、ゼロは合計に何も寄与しません。 txnTypeと一致します。
SELECT
SUM(IF(trx.txnType IN ('REFUND', 'VOID'), trx.totalAmount, 0)) AS refunds,
SUM(IF(trx.txnType = 'SALE' AND trx.billingCycleNumber != 1, trx.totalAmount, 0)) AS lifetimeRevenue
FROM trx
WHERE trx.clientOrderId IN (
'B6A8DB9568', '6E7705B487', '59C4D4234D', '1D9CD4EF96',
'4C373E8CDE', 'E818BEE48F', '6610555669', 'ECF388E288',
'32FD93075C', 'B03417425B', '18FD77061A', '1C39E4BD04',
'C92B970E55', '0920F06DFA', 'EEFB4AAADA', 'FC2D9FF9AD')
AND trx.txnType IN ('REFUND', 'VOID', 'SALE');
このクエリでは、(clientOrderId)のインデックスが必要です。 2つのIN()
述部があるので、WHERE節は索引の最初の列の索引のみを使用します。
WHERE句のインデックスを使用しないため、FIND_IN_SET()式は使用しないでください。
あなたはクエリに10個以上の用語があると言いました。だから私は、それらの言葉でいくつかの異なるタイプの表現があると予想しています。私は "次の言葉が別の何かのように見えたら..."と答えるつもりはない。サブクエリを1つのシングルパスクエリに解く方法を示しました。あなたの質問の他の言葉にそれを適用することはあなた次第です。ここで
は、私がテストしたデモです:各用語について
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+
| 1 | PRIMARY | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
| 3 | SUBQUERY | trx | NULL | ALL | NULL | NULL | NULL | NULL | 2 | 50.00 | Using where |
| 2 | SUBQUERY | trx | NULL | ALL | NULL | NULL | NULL | NULL | 2 | 50.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+
お知らせ1つのサブクエリ、それぞれが "タイプ=すべて" を行います。
create table trx (
clientOrderId char(10),
txnType enum('REFUND','VOID','SALE'),
totalAmount numeric(9,2),
billingCycleNumber int default 0,
key (clientOrderId)
);
+---------------+---------+-------------+--------------------+
| clientOrderId | txnType | totalAmount | billingCycleNumber |
+---------------+---------+-------------+--------------------+
| B6A8DB9568 | REFUND | 42.00 | 0 |
| 59C4D4234D | SALE | 84.00 | 0 |
+---------------+---------+-------------+--------------------+
はここにあなたのクエリのEXPLAINですそのテーブルアクセスとして。
は、ここに私のクエリのEXPLAINです:
+----+-------------+-------+------------+-------+---------------+---------------+---------+------+------+----------+------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+---------------+---------+------+------+----------+------------------------------------+
| 1 | SIMPLE | trx | NULL | range | clientOrderId | clientOrderId | 11 | NULL | 16 | 50.00 | Using index condition; Using where |
+----+-------------+-------+------------+-------+---------------+---------------+---------+------+------+----------+------------------------------------+
一つの簡単なテーブル・アクセス、インデックスを使用します。
クエリと私が試した例のデータを与えられた私のクエリの両方からの結果:
+---------+-----------------+
| refunds | lifetimeRevenue |
+---------+-----------------+
| 42.00 | 84.00 |
+---------+-----------------+
いけない使用 'find_in_set'。 'IN'を使用 – GurV