PostgreSQL 搜索条件必须输出丢失的行
PostgreSQL search criteria must output missing row
我有两个 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 表中的一行。例如;我有 'Mary',它拥有:'BMW'、'MERC'、'VW'、'AUDI'。
我有 'Paul',它只拥有:'BMW'、'MERC'、'VW'。
我的查询将显示 Mary 和 Paul,因为他们都拥有 'BMW'、'MERC'、'VW'。
我只想在结果中看到 'Paul',因为他缺少 'AUDI'。
请注意,我不是数据库专家,我将不胜感激任何帮助和帮助。
提前致谢。
将其与 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
之间进行外部联接
我需要输出所有拥有 'BMW'、'MERC' 和 'VW' 但不是 'AUDI'.[=29= 的员工] 如果你需要员工是不同的,而不是员工+汽车品牌对,你可以通过聚合来做到这一点:
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' 的员工(如您建议的问题).
Edit:对于较旧的 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
我有两个 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 表中的一行。例如;我有 'Mary',它拥有:'BMW'、'MERC'、'VW'、'AUDI'。 我有 'Paul',它只拥有:'BMW'、'MERC'、'VW'。 我的查询将显示 Mary 和 Paul,因为他们都拥有 'BMW'、'MERC'、'VW'。
我只想在结果中看到 'Paul',因为他缺少 'AUDI'。
请注意,我不是数据库专家,我将不胜感激任何帮助和帮助。 提前致谢。
将其与 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
之间进行外部联接我需要输出所有拥有 'BMW'、'MERC' 和 'VW' 但不是 'AUDI'.[=29= 的员工] 如果你需要员工是不同的,而不是员工+汽车品牌对,你可以通过聚合来做到这一点:
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' 的员工(如您建议的问题).
Edit:对于较旧的 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