PostgreSQL搜索条件必须输出缺失的行

时间:2017-04-03 07:24:54

标签: sql postgresql postgresql-9.2

我有两个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','大众'。

我只想在结果中看到'保罗',因为他错过了'奥迪'。

请注意,我不是数据库专家,我将不胜感激任何帮助和帮助。 提前谢谢。

2 个答案:

答案 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'的员工(如您提出的问题)。

http://rextester.com/MQL14836

修改:对于较旧的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

http://rextester.com/KHMW56692