简体   繁体   中英

Excluding records from SQL query

Given one or more owner_ids (for instance, 2, 4, and 6), I would like to return the list of resources.id linked to owners by owners_has_resources . No problem, I could just do SELECT DISTINCT ohr.resources_id FROM owners_has_resources ohr WHERE ohr.owners_id IN (2,4,6);

Now the part I am stuck on. I would like to return the list of resources.id the same as above, but exclude any that are also linked to non-deleted owners (as determined by owners.deleted!=true ) where the link is not deleted (as determined by owners_has_resources.deleted!=true )

It can be assumed that owners.deleted is true for all the originally provided owners_ids (ie 2, 4, 6)

For instance, given owners_ids 2 and 4, I should return resources_id 2 and 3. Note that I meant to say deleted=TRUE indicates it was deleted, but since answers have been posted that used the previous, I won't be editing the question. Instead, the truth table below shows owner_not_deleted and resource_not_deleted .

+-----------+-------------------+--------------+----------------------+
| owners_id | owner_not_deleted | resources_id | resource_not_deleted |
+-----------+-------------------+--------------+----------------------+
|         2 | FALSE             |            1 | TRUE                 |
|         2 | FALSE             |            2 | TRUE                 |
|         4 | FALSE             |            2 | TRUE                 |
|         4 | FALSE             |            3 | TRUE                 |
|         5 | TRUE              |            1 | FALSE                |
|         5 | TRUE              |            2 | TRUE                 |
|         7 | TRUE              |            2 | FALSE                |
+-----------+-------------------+--------------+----------------------+

owners
- id (INT PK)
- name, etc
- deleted (true/false)

resources
- id (INT PK)
- name, etc

owners_has_resources
- owners_id (INT PK REFERENCES owners.id)
- resources_id (INT PK REFERENCES resources.id)
- deleted (true/false)

What about

SELECT DISTINCT ohr.resources_id 
FROM owners_has_resources ohr 
JOIN owners o ON ohr.owners_id = o.id
WHERE ohr.owners_id IN (2,4,6)
AND (o.deleted = FALSE OR ohr.deleted = FALSE);

First you pick the data you want then you only select those which are not referenced by non deleted owners in the NOT EXISTS block

SELECT DISTINCT ohr.resources_id 
FROM owners_has_resources ohr 
JOIN owners o ON ohr.owners_id = o.id
WHERE ohr.owners_id IN (2,4,6)
AND NOT EXISTS (
    SELECT NULL FROM owners_has_resources ohr2 
    JOIN owners o2 ON ohr2.owners_id = o2.id
    WHERE ohr2.deleted=FALSE 
    AND o2.deleted=FALSE
    AND ohr.resources_id=ohr2.resources_id 
)
SELECT DISTINCT ohr1.resources_id
FROM owners_has_resources ohr1
LEFT OUTER JOIN owners_has_resources ohr2 ON ohr2.resources_id=ohr1.resources_id AND ohr2.deleted = TRUE
LEFT OUTER JOIN owners o ON o.id=ohr2.owners_id AND ohr2.deleted = TRUE
WHERE ohr1.owners_id IN (2,4,6) AND o.id IS NULL;

or

SELECT DISTINCT ohr1.resources_id
FROM owners_has_resources ohr1
LEFT OUTER JOIN owners_has_resources ohr2 ON ohr2.resources_id=ohr1.resources_id
LEFT OUTER JOIN owners o ON o.id=ohr2.owners_id
WHERE ohr1.owners_id IN (2,4,6) AND o.id IS NULL AND ohr2.deleted = TRUE AND ohr2.deleted = TRUE;

I would appreciate any comments on whether one approach is better than the other.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM