我有这个查询:
SELECT c.id contact_id, engagement.sent
FROM contact c
LEFT JOIN (
/* ➊ Inner query */
SELECT eq.contact_id contact_id, COUNT(*) sent
FROM mailing_job j
INNER JOIN mailing_event_queue eq ON eq.job_id = j.id
WHERE j.end_date > NOW() - INTERVAL 3 MONTH
GROUP BY eq.contact_id
) engagement ON engagement.contact_id = c.id
WHERE
/* ➋ various conditions on table 'c' */
do_not_email = 0 AND is_opt_out = 0 AND is_deceased = 0 AND is_deleted = 0
AND contact_type = 'Individual'
/* ➌ */
AND EXISTS (
SELECT gc.contact_id
FROM group_contact gc
WHERE gc.contact_id = c.id AND gc.group_id IN (30,386,14,6,214,5,88,361,334,18,9,17,240,7,13,10,292,291,290,12)
)
/* ➍ AND c.id=1 */
ORDER BY c.id
- 内部查询 ➊ 自行运行时会产生结果,例如sent: 15 for contact 1。这是正确的、预期的数据。
- 但是,运行整个查询会为整个发送的列提供NULL!这让我很烦恼。
- 消除 ➋ 处的 WHERE 子句,或消除 ➌ 处的 EXISTS,或包括注释掉的 ➍ 子句会导致其运行并返回sent: 15用于测试联系人。
我在 MariaDB 10.3 上。
编辑
希望增加清晰度。从根本上说,这很奇怪——我认为——而且可能是 MariaDB 中的一个错误,尽管我希望不会!
内部查询 ➊ 返回行,例如
contact_id sent
1 15
...
主查询还使用 ID 获取联系人1
。
现在在我所有的岁月里,当我离开加入一个主键(即c.id
)上的表时,子查询中的记录匹配,它从来没有改变它的值。
这些值随着其他 WHERE 子句的变化而变化,但在某种程度上仍然意味着外部查询会生成匹配的联系人 ID,我认为这很奇怪。
我真的希望我做了一些愚蠢的事情,但我看不到它。
这看起来像一个错误。请向 MariaDB 发送错误报告。一些细节:
首先,确保它是一个错误。
查询 A 生成单行(假设
contact (id)
具有唯一(或主键)约束:查询 B 产生一行(值
15
在 中sent
)查询 C 生成单行但具有值
NULL
(或与查询 B 中的值不同的任何内容15
)。如果确实发生了上述情况,则几乎可以肯定是表/索引中的错误或损坏的数据。
其他要检查/添加到报告中的事项:
EXPLAIN SELECT ...
)CREATE TABLE
所有涉及的表,包括索引。你可以使用SHOW CREATE TABLE tablename ;
它。select version();
)。删除其中的每一项:
去除
ORDER BY
删除子查询 3 和/或 4。
在 b 子查询中添加条件:
将整个查询重写为:
结合上述任何或所有重写和测试执行计划和结果,并将未能产生正确结果的那些(查询和计划)添加到报告中。
建议在最新的子版本中进行测试,因为这可能是一个已修复的错误。
试试这个 C 的重新表述: