I'll start off with the schema:
CREATE TABLE CustomersActions (
`caID` int(10) unsigned NOT NULL AUTO_INCREMENT primary key,
`cusID` int(11) unsigned NOT NULL,
`caTimestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
)
CREATE TABLE `Assignments` (
`asgID` int(10) unsigned NOT NULL AUTO_INCREMENT primary key,
`cusID` int(11) unsigned NOT NULL,
`asgAssigned` date DEFAULT NULL,
`astID` int(10) unsigned NOT NULL
)
CREATE TABLE `AssignmentStatuses` (
`astID` int(10) unsigned NOT NULL AUTO_INCREMENT primary key,
`astStatus` varchar(255) DEFAULT ''
)
My original query is:
SELECT DISTINCT
ca.cusID
FROM
CustomersActions ca
WHERE
NOT EXISTS (
SELECT
TRUE
FROM
Assignments asg
NATURAL JOIN AssignmentStatuses
WHERE
asg.cusID = ca.cusID
AND (
DATE_ADD(asgAssigned, INTERVAL 6 DAY) > NOW()
OR astStatus IN('Not contacted', 'Follow-up')
)
)
What this does is select all cusID
entries from CustomersActions if said Customer does not have a row in Assignments
that is in "Not contacted" or "Follow-up" (for any date range) OR has an assignment of any status from less than six days ago.
I tried writing the same query using LEFT JOIN
to exclude from Assignments
like so:
SELECT DISTINCT
ca.cusID
FROM
CustomersActions ca
LEFT JOIN (
Assignments asg
NATURAL JOIN AssignmentStatuses
) ON (ca.cusID = asg.cusID)
WHERE
asgID IS NULL
OR DATE_ADD(asgAssigned, INTERVAL 6 DAY) < NOW()
OR astStatus IN('Not contacted', 'Follow-up')
The problem is that it's possible for a customer to have multiple entries in Assignments
so a cusID
can be selected even if they have an existing row that should force them to be excluded. This makes sense to me, and the NOT EXISTS
solves this problem.
What I'm wondering is if there is a way to perform a single query that has the same effect as the query when using NOT EXISTS
. That is, a customer should be excluded if they have any rows that satisfy the exclusion condition, not only if all of their rows satisfy the exclusion condition (or if they have none).