SQL语句选择具有特定值的列

时间:2018-09-29 14:49:20

标签: sql postgresql

我需要一些帮助来制作一条sql语句;我真的不知道该如何处理这种情况。我有两个表,部门和员工 我要从中选择拥有至少一名雇员并且所有雇员都来自巴塞罗那的部门的 Dpt_num Dpt_name

案例1

== Departments =======
| Dpt_num | Dpt_name |
|    1    |    A     |
|    2    |    B     |

== Employees ===================
| E_num | Dpt_num |  City      |
|  1    |   1     | Barcelona  |
|  2    |   1     | Barcelona  |

在这种情况下的结果应该是

 Dpt_num Dpt_name
 ------------------
    1       A

案例2

== Departments =======
| Dpt_num | Dpt_name |
|    1    |    A     |
|    2    |    B     |

== Employees ==================
| E_num | Dpt_num | City      |
|   1   |    1    | Barcelona |
|   2   |    1    | Madrid    |

在这种情况下,结果应该为空。

例如,我尝试过此操作,但效率似乎很低,并且并非在所有情况下都有效

select
    num_dpt, nom_dpt
from
    departements
where
    1 = (select count(distinct e.ciutat_empl)
         from empleats e
         where e.num_dpt = num_dpt)
    and not exists (select * from empleats e
                    where e.ciutat_empl != 'BARCELONA' and e.num_dpt = num_dpt);

非常感谢您的帮助。谢谢!

6 个答案:

答案 0 :(得分:2)

您想在where子句中进行过滤。然后,使用existsnot exists

select d.num_dpt, d.nom_dpt 
from departaments d
where exists (select 1
              from empleats e
              where e.num_dpt = d.num_dpt and e.ciutat_empl = 'BARCELONA' 
             ) and
      not exists (select 1
                  from empleats e
                  where e.num_dpt = d.num_dpt and e.ciutat_empl <> 'BARCELONA' 
             );

第一个条件检查至少一名雇员来自巴塞罗那。第二个检查没有员工来自其他城市。

您的版本中的一个主要问题是相关子句:

e.num_dpt = num_dpt

您认为这是在做

e.num_dpt = departaments.num_dpt

但这确实在做:

e.num_dpt = e.num_dpt

始终限定您的列名。当查询中有多个表引用时,这一点尤其重要。

答案 1 :(得分:1)

加入表格,按部门分组,检查巴塞罗那的员工人数是否等于部门所有雇员的人数。

SELECT d.dpt_num,
       d.dpt_name
       FROM departments d
            INNER JOIN employees e
                       ON e.dpt_num = d.dpt_num
       GROUP BY d.dpt_num,
                d.dpt_name
       HAVING count(CASE
                      WHEN e.city = 'Barcelona' THEN
                        1
                    END) = count(*);

答案 2 :(得分:1)

我认为这应该有效:

select d.dpt_num, d.dpt_name
from departments d
inner join employees e on
  d.dpt_num = e.dpt_num
group by d.dpt_num, d.dpt_name
having count(*) = sum(case when e.city = 'Barcelona' then 1 else 0 end)
  • INNER JOIN确保至少有1名员工
  • HAVING count(*) = sum(case when e.city = 'Barcelona' then 1 else 0 end)确保所有员工都来自巴塞罗那

答案 3 :(得分:1)

通常来说,您将COUNT(*)COUNT(some condition)进行比较以解决此类问题:

SELECT *
FROM Departments
WHERE EXISTS (
    SELECT 1
    FROM   Employees
    WHERE  Employees.Dpt_num = Departments.Dpt_num
    HAVING COUNT(*) > 0 -- it is possible to get a 0 if where did not match
    AND    COUNT(*) = COUNT(CASE WHEN Employees.City = 'Barcelona' THEN 1 END)
)

DB Fiddle

答案 4 :(得分:1)

demo: db<>fiddle

SELECT dpt_num, dpt_name
FROM (
    SELECT d.dpt_num, d.dpt_name, array_agg(city) as cities
    FROM dept d
    JOIN empl e
    ON d.dpt_num = e.dpt_num
    GROUP BY d.dpt_num, d.dpt_name
) s
WHERE 'Barcelona' = ALL(cities)

汇总城市,然后可以使用ALL运算符进行过滤,该运算符将检查所有数组元素是否都符合条件。

答案 5 :(得分:0)

请在下面尝试查询

select a.dpt_number,a.dpt_name from yy_department a 
where exists (select 'x' from yy_employees y where y.dpt_number = a.dpt_number and y.city = 'Barcelona') 
and not exists (select 'x' from yy_employees y where y.dpt_number = a.dpt_number and nvl(y.city,'x') <> nvl('Barcelona','y'))