PostgreSQL 搜索条件必须输出缺失的行
Posted
技术标签:
【中文标题】PostgreSQL 搜索条件必须输出缺失的行【英文标题】:PostgreSQL search criteria must output missing row 【发布时间】:2017-04-03 07:24:53 【问题描述】:我有两个 postgreSQL 表,即:employees 和 employee_cars。 我需要输出拥有“BMW”、“MERC”和“VW”但不拥有“AUDI”的所有员工。
我尝试过以下查询:
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 表中的一行。例如,例如;我有“玛丽”,它拥有:“宝马”、“MERC”、“大众”、“奥迪”。 我有“保罗”,它只拥有:“宝马”、“MERC”、“大众”。 我的查询将显示 Mary 和 Paul,因为他们都拥有“BMW”、“MERC”、“VW”。
我只想在结果中看到“Paul”,因为他缺少“AUDI”。
请注意,我不是数据库专家,我将不胜感激任何帮助和帮助。 提前致谢。
【问题讨论】:
哦,我明白了。 “BMW”、“MERC”AND“VW”实际上是指“BMW”、“MERC”或“VW”,对吗? @Laurenz Albe,没有一点复杂:'BMW', 'MERC' AND 'VW'
AND NOT 'AUDI'
【参考方案1】:
我需要输出拥有“BMW”、“MERC”和“VW”但不是“AUDI”的所有员工。如果您需要区分员工,而不是员工 + 汽车品牌对,您可以通过聚合来做到这一点:
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
ing:
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
【讨论】:
我相信这个解决方案会起作用,但是我遇到了过滤计数的问题。我有 PG 版本 9.2。 @JP_CNTLM_ADMIN 你可以使用COUNT(CASE ...)
。我会尽快更新我的答案。
谢谢!像魅力一样工作......您先生,是一个传奇!【参考方案2】:
将此与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);
请注意,您不需要在 employees 和 employee_cars 之间进行外部连接
【讨论】:
嗨@a_horse_with_no_name,感谢您的反馈。你的建议很有效。问题在于 My 和您的IN
语句,即使员工仅拥有一辆车,查询也会返回结果,例如“John”仅拥有“BMW”。我需要结果只输出拥有所有 3 'BMW'、'MERC'、'VW' 而不是“AUDI”的员工。以上是关于PostgreSQL 搜索条件必须输出缺失的行的主要内容,如果未能解决你的问题,请参考以下文章