non_informative
とdata
テーブルの間にデカルト積があります。(列がどのテーブルからのものかはまったく明確ではありませんticker
。
non_informative
「コメント」が返されるために必要なのは、(クエリの述語を満たすために)コメントと「一致」しない行が 1 つ見つかることだけであることを理解してください。一致する non_informative の行があるかもしれませんが、クエリはそれらを気にしません。クエリは、一致しない行の存在のみを探しています。クエリは、non_informative のすべての行に一致する場合にのみ「コメント」が除外されることを効果的に示しています。
non_informative に一致する行がない "comment" の値を返したい場合は、別のクエリが必要です。ticker
(列はテーブルからのものであると仮定しdata
ます。)
の空の文字列値のコーナー ケースも除外しますitem
。これは、comment のすべての非 null 値に本質的に「一致」するためです。
-- NOT EXISTS 述語の使用:
SELECT d.comment
FROM `data` d
WHERE d.ticker != 'O'
AND d.source != 7
AND d.source != 6
AND NOT EXISTS
( SELECT 1
FROM `non_informative` n
WHERE n.item <> ''
AND d.comment LIKE CONCAT('%',n.item,'%')
)
GROUP BY d.comment
ORDER BY d.comment
-- または、アンチ結合を使用して:
SELECT d.comment
FROM `data` d
LEFT
JOIN ( SELECT n.item
FROM `non_informative` n
WHERE n.item <> ''
GROUP BY n.item
) m
ON d.comment LIKE CONCAT('%',m.item,'%')
WHERE d.ticker != 'O'
AND d.source != 7
AND d.source != 6
AND m.item IS NULL
GROUP BY d.comment
ORDER BY d.comment
これら 2 つのステートメントは、同等の結果セットを返します (ただし、元のクエリの結果セットとは異なります)。また、異なるパフォーマンス特性を示す可能性があります (MySQL のバージョンや、MySQL エンジンが NOT EXISTS 述語を結合防止操作に変換できるかどうかによって異なります...パフォーマンスは、使用可能なインデックスと生成されるインデックスによって異なります)。実行計画。)
空の文字列のコーナーケースを気にしなければ、2 番目のステートメントを少し単純化できます...
SELECT d.comment
FROM `data` d
LEFT
JOIN `non_informative` n
ON d.comment LIKE CONCAT('%',n.item,'%')
WHERE d.ticker != 'O'
AND d.source != 7
AND d.source != 6
AND n.item IS NULL
GROUP BY d.comment
ORDER BY d.comment
基本的に、テーブル内のすべての行について、data
テーブル内の「一致」をチェックしていnon_informative
ます。「一致」が見つかった行は、「n.item IS NULL」述語によって除外されます。data
で一致する行が見つからない行の場合non_informative
、LEFT JOIN 操作は「item」列に NULL 値を生成するため、その行は結果セットに含まれます。
パフォーマンス:
元のクエリにはインライン ビューが含まれています (エイリアスはt
)。MySQL は、外側のクエリが実行される前に、それを中間の MyISAM テーブルとして実体化します。そして、そのような考え方は、大きなテーブルではパフォーマンスを著しく低下させる可能性があります。
しかし、そのステートメントを「調整」する前に、正しい結果セットを返すステートメントが本当に必要です。(演習としての場合を除き、目的の結果セットが返されない場合、そのステートメントを書き直す意味はありません。)