你在non_informative
和data
表之间有一个笛卡尔积。(根本不清楚该列ticker
来自哪个表。
了解要返回的“评论”,所需要的(满足查询中的谓词)就是找到non_informative
与评论不“匹配”的一行。non_informative 中可能有匹配的行,但您的查询并不关心这些。您的查询只是寻找不匹配的行的存在。该查询实际上是说,只有当它与非信息性中的每一行匹配时,才会排除“评论”。
如果您要返回的是 non_informative 中没有匹配行的“comment”值,则需要不同的查询。(我将假设该ticker
列来自data
表格。)
我还将排除空字符串值的极端情况item
,因为这将基本上“匹配”每个非空值以进行注释。
-- 使用 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
这两个语句应该返回一个等效的结果集(但与原始查询的结果集不同)。它们也可能表现出不同的性能特征(取决于 MySQL 的版本,以及 MySQL 引擎是否可以将 NOT EXISTS 谓词转换为反连接操作......性能实际上取决于可用的索引和生成的索引执行计划。)
如果我们不关心空字符串的极端情况,我们可以稍微简化第二个语句......
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 表。这种想法可能是大型表的真正性能杀手。
但在我们“调整”该语句之前,我们确实需要一个返回正确结果集的语句。(如果它没有返回所需的结果集,那么重写该语句是没有意义的,除非作为练习。)