1

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).

4

1 回答 1

0

您是否尝试过使用NOT IN子句,例如:

SELECT DISTINCT
  ca.cusID
FROM
 CustomersActions ca
WHERE cusID    
 NOT IN (
    SELECT
       cusID
    FROM
       Assignments asg
       INNER JOIN AssignmentStatuses ast
       ON asg.astID = ast.astID
       WHERE
          DATE_ADD(asgAssigned, INTERVAL 6 DAY) > NOW()
          OR astStatus IN('Not contacted', 'Follow-up')
 )
于 2013-06-24T00:29:40.720 回答