I have this query:
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
- The inner query ➊ when run on its own yields results, e.g. sent: 15 for contact 1. This is the correct, expected data.
- However, running the whole query gives NULL for the whole sent column! Which is vexing me.
- Eliminating the WHERE clauses at ➋, or eliminating the EXISTS at ➌, or including the commented out ➍ clause causes it to behave and return sent: 15 for the test contact.
I'm on MariaDB 10.3.
EDIT
Hoping to add clarity. Fundamentally this is weird -I think- and possibly a bug in MariaDB, though I hope not!
The Inner query ➊ returns rows, e.g.
contact_id sent
1 15
...
The main query also picks up contact with ID 1
.
Now in all my years, when I've left joined a table on a primary key (i.e. c.id
) where a record in the subquery matches, it's never changed its values.
The fact that those values come and go with changing other WHERE clauses, but in ways that still mean the outer query generates the matching contact ID, I think, is weird.
I'm really hoping I've done something stupid, but I can't see it.
Best Answer
This looks like a bug. Please send a bug report to MariaDB. Some details:
First, make sure it is a bug.
Query A produces a single row (assuming that
contact (id)
has a unique (or primary key) constraint:Query B produces one row (with value
15
insent
)Query C produces a single row but with value
NULL
(or anything different than the15
in Query B).If the above do happen, it's almost surely either a bug or corrupted data in tables/indexes.
Other things to check / add to the report:
EXPLAIN SELECT ...
)CREATE TABLE
for all tables involved, including indexes. You can useSHOW CREATE TABLE tablename ;
for that.select version();
).remove each one of these:
remove the
ORDER BY
remove subqueries 3 and/or 4.
add a condition in b subquery:
rewrite the whole query as:
combine any or all of the above rewrites and test execution plans and results and add to the report the ones (queries and plans) that fail to produce correct results.
Testing in the latest subversions is recommended, as this may be a bug that has been fixed.