聚合子查询

时间:2018-12-19 19:30:45

标签: sql sql-server sql-server-2017

我很难找到如何从员工最多的表中获取项目编号或项目名称

create table Pro_works_on
(
    EID char(9) ,
    PNO char(9) ,
    Pro_HOURS smallint not null,
    constraint pk_Pro_works_on primary key(EID,PNO),
);

SELECT
  p.PNO
FROM
  Pro_works_on AS p
 ,(
    SELECT
      COUNT(p.EID) AS numOfEmployee
     ,p.PNO
    FROM
      Pro_works_on AS p
    GROUP BY
      p.PNO
  ) AS L
WHERE
  MAX(L.numOfEmployee) = COUNT(p.EID);

它会产生以下错误:

  

子查询返回了多个值。当子查询遵循=,!=,<,<=,>,> =或将子查询用作表达式时,不允许这样做。

5 个答案:

答案 0 :(得分:2)

使用order by和某种限制子句-如果需要一行。在标准SQL中:

select p.PNO, count(*) as numOfEmployee 
from Pro_works_on p
group by p.PNO
order by count(*) desc
fetch first 1 row only;

在SQL Server中,您可以将top (1) or顶部(1)与领带一起使用:

select top (1) p.PNO, count(*) as numOfEmployee 
from Pro_works_on p
group by p.PNO
order by count(*) desc;

答案 1 :(得分:2)

对于汇总结果,您应该使用had for过滤器,而不是

select L.PNO 
    from Pro_works_on p, (
    select count(p.EID) as numOfEmployee
    ,p.PNO
    from Pro_works_on p
    group by p.PNO) L
HAVING  MAX(L.numOfEmployee)=numOfEmployee

但是也许您可以使用一种更简单的方法来避免与组有关的问题,方法是使用命令by和限制1

    select L.PNO 
    (
        select count(p.EID) as numOfEmployee
        , p.PNO
        from Pro_works_on p
        group by p.PNO
    ) L 
    order by numOfEmployee DESC 
    LIMIT 1 

答案 2 :(得分:1)

将您的问题分解为若干步骤。

首先,您需要知道每个项目分配了多少名员工。这样一来,您将知道哪个员工最多。为此,请将public static String loadFacultat(String archivo) { Gson gson = new Gson(); BufferedReader bf = null; try{ bf = new BufferedReader(new FileReader(FACULTATFOLDER + archivo)); Facultat facultat = gson.fromJson(bf,Facultat.class); return gson.toJson(facultat); } catch(Exception e){ System.out.println(e.toString()); } return null; } COUNT一起使用。

GROUP BY

接下来,让您的查询使用SELECT p.PNO, COUNT(p.EID) AS numOfEmployee FROM Pro_works_on AS p GROUP BY p.PNO 将结果按所需的顺序排列。您希望拥有最多员工的项目排在第一位,因此请按ORDER BY的降序排列。

DESC

最后,由于您只关心一个拥有最多员工的项目,因此添加行限制器。在SQL Server中,您可以使用SELECT p.PNO, COUNT(p.EID) AS numOfEmployee FROM Pro_works_on AS p GROUP BY p.PNO ORDER BY COUNT(p.EID) DESC; 表达式来实现。而且,由于您只关心项目编号,而不关心员工的实际人数,因此可以从结果中取出TOP (N),然后将其保留在COUNT中。

ORDER BY

编辑:根据评论中OP的问题添加了SELECT TOP(1) WITH TIES p.PNO FROM Pro_works_on AS p GROUP BY p.PNO ORDER BY COUNT(p.EID) DESC;

答案 3 :(得分:1)

如果您需要返回多个项目(如果每个项目都有最多的雇员),则可以使用窗口函数进行汇总,然后按该函数进行过滤。

SELECT *
FROM (
    SELECT p.PNO
        , count(*) AS empCount
        , RANK() OVER (ORDER BY count(*) DESC) AS r
    FROM Pro_works_on p
    GROUP BY p.PNO
) s1
WHERE r = 1

这将按顺序对所有员工进行排名,并将所有最高员工人数的排名设置为1。然后只需选择所有员工排名为1。

答案 4 :(得分:0)

要使项目拥有最多的员工人数,我会做:

with
x as (
  select
    pno,
    count(eid) as tot_emp
  from pro_works_on
  group by pno
),
y as (
  select max(tot_emp) as max_emp from x
)
select 
  x.pno
from x
join y on y.max_emp = x.tot_emp