我有两个postgreSQL表,即:员工和 employee_cars 。 我需要输出所有拥有'宝马','MERC'和'大众'的员工,但不是'奥迪'。
我在下面尝试过查询:
SELECT DISTINCT a.employee_name, b.car_brand
FROM employees a
LEFT JOIN employee_cars b
ON a.employee_id = b.employee_id
WHERE b.car_brand IN ('BMW','MERC','VW')
AND b.car_brand NOT LIKE 'AUDI';
以下输出:
employee_name,car_brand
"Mary","BMW"
"Mary","MERC"
"Mary","VW"
"Paul","BMW"
"Paul","MERC"
"Paul","VW"
问题是员工拥有的每辆车都是employee_cars表中的一行。所以例如;我拥有'Mary',拥有:'宝马','MERC','大众','奥迪'。 我有'保罗'只拥有:'宝马','MERC','大众'。 我的询问将显示玛丽和保罗,因为他们都拥有'宝马','MERC','大众'。
我只想在结果中看到'保罗',因为他错过了'奥迪'。
请注意,我不是数据库专家,我将不胜感激任何帮助和帮助。 提前谢谢。
答案 0 :(得分:1)
将此与not exists
条件相结合:
SELECT distinct emp.employee_name, ec.car_brand
FROM employees emp
JOIN employee_cars ec ON emp.employee_id = ec.employee_id
WHERE ec.car_brand IN ('BMW','MERC','VW')
and not exists (select *
from employee_cars ec2
where ec2.car_brand = 'AUDI'
and ec2.employee_id = emp.employee_id);
请注意,您不需要员工和employee_cars之间的外部联接
答案 1 :(得分:1)
我需要输出所有拥有'宝马','MERC'和'大众'但不是'奥迪'的员工。如果您需要员工与众不同,而不是员工+汽车品牌对,你可以用聚合来做到这一点:
SELECT e.employee_name, string_agg(c.car_brand, ', ')
FROM employees e
JOIN employee_cars c ON e.employee_id = c.employee_id
GROUP BY e.employee_id
HAVING COUNT(1) FILTER (WHERE c.car_brand IN ('BMW', 'MERC', 'VW')) = 3
AND COUNT(1) FILTER (WHERE c.car_brand = 'AUDI') = 0
这也将过滤掉没有'BMW','MERC'或'VW'的员工(如您提出的问题)。
修改:对于较旧的PostgreSQL版本,请使用CASE
表达式而不是FILTER
:
SELECT e.employee_name, string_agg(c.car_brand, ', ')
FROM employees e
JOIN employee_cars c ON e.employee_id = c.employee_id
GROUP BY e.employee_id
HAVING COUNT(CASE WHEN c.car_brand IN ('BMW', 'MERC', 'VW') THEN 1 END) = 3
AND COUNT(CASE WHEN c.car_brand = 'AUDI' THEN 1 END) = 0