Sql 带聚合的子查询
我很难找到如何从员工最多的表中获取项目编号或项目名称Sql 带聚合的子查询,sql,sql-server,sql-server-2017,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.
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);
它会产生以下错误:
子查询返回了多个值。当子查询在=、!=、=或者当子查询用作表达式时
如果您想要一行,请使用
orderby
和某种限制子句。在标准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)或top(1):
select top (1) p.PNO, count(*) as numOfEmployee
from Pro_works_on p
group by p.PNO
order by count(*) desc;
如果您想要一行,请使用orderby
和某种限制子句。在标准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)或top(1):
select top (1) p.PNO, count(*) as numOfEmployee
from Pro_works_on p
group by p.PNO
order by count(*) desc;
对于聚合结果,您应该将having用作filter,而不是where
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
但可能是您可以使用一种更简单的方法,通过使用order by和limit 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
对于聚合结果,您应该将having用作filter,而不是where
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
但可能是您可以使用一种更简单的方法,通过使用order by和limit 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
为了让项目拥有最多的员工,我会:
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
为了让项目拥有最多的员工,我会:
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
把你的问题分解成几个步骤
首先,您需要知道每个项目分配了多少员工。这样你就知道哪家公司的员工最多了。要做到这一点,请将COUNT
与groupby
一起使用
SELECT
p.PNO, COUNT(p.EID) AS numOfEmployee
FROM
Pro_works_on AS p
GROUP BY
p.PNO
SELECT TOP(1) WITH TIES
p.PNO
FROM
Pro_works_on AS p
GROUP BY
p.PNO
ORDER BY COUNT(p.EID) DESC;
接下来,使用orderby
,让您的查询将结果按您想要的顺序排列。你想让员工最多的项目排在第一位,所以把他们放在DESC
结束顺序中
SELECT
p.PNO, COUNT(p.EID) AS numOfEmployee
FROM
Pro_works_on AS p
GROUP BY
p.PNO
ORDER BY COUNT(p.EID) DESC;
最后,因为您只关心员工最多的一个项目,所以添加一个行限制器。在SQL Server中,可以使用TOP(N)
表达式来实现这一点。而且,由于您只关心项目编号,而不关心员工的实际数量,因此您可以从结果中提取计数
,并将其按的顺序保留
SELECT
p.PNO, COUNT(p.EID) AS numOfEmployee
FROM
Pro_works_on AS p
GROUP BY
p.PNO
SELECT TOP(1) WITH TIES
p.PNO
FROM
Pro_works_on AS p
GROUP BY
p.PNO
ORDER BY COUNT(p.EID) DESC;
编辑:根据OP在评论中提出的问题添加了带领带的。将问题分解为几个步骤
首先,您需要知道每个项目分配了多少员工。这样你就知道哪家公司的员工最多了。要做到这一点,请将COUNT
与groupby
一起使用
SELECT
p.PNO, COUNT(p.EID) AS numOfEmployee
FROM
Pro_works_on AS p
GROUP BY
p.PNO
SELECT TOP(1) WITH TIES
p.PNO
FROM
Pro_works_on AS p
GROUP BY
p.PNO
ORDER BY COUNT(p.EID) DESC;
接下来,使用orderby
,让您的查询将结果按您想要的顺序排列。你想让员工最多的项目排在第一位,所以把他们放在DESC
结束顺序中
SELECT
p.PNO, COUNT(p.EID) AS numOfEmployee
FROM
Pro_works_on AS p
GROUP BY
p.PNO
ORDER BY COUNT(p.EID) DESC;
最后,因为您只关心员工最多的一个项目,所以添加一个行限制器。在SQL Server中,可以使用TOP(N)
表达式来实现这一点。而且,由于您只关心项目编号,而不关心员工的实际数量,因此您可以从结果中提取计数
,并将其按的顺序保留
SELECT
p.PNO, COUNT(p.EID) AS numOfEmployee
FROM
Pro_works_on AS p
GROUP BY
p.PNO
SELECT TOP(1) WITH TIES
p.PNO
FROM
Pro_works_on AS p
GROUP BY
p.PNO
ORDER BY COUNT(p.EID) DESC;
编辑:根据OP在评论中提出的问题添加了带有关系的。如果需要返回多个项目(如果每个项目的员工人数最多),则可以使用窗口函数进行聚合,然后按此进行筛选
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的 如果需要返回多个项目(如果每个项目都有最多的员工),则可以使用窗口函数进行聚合,然后按此进行筛选
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的 但它不能满足我的需要。我需要的是员工人数最多的项目。这里只给我每个项目的编号。@MikaAzulay。你运行过这个查询吗?它为项目提供了最多的员工。对于SQL Server,这将需要在FETCH
语句之前使用OFFSET 0行
。RE:。它将在TOP
上提供一些性能改进。(我不认为它能用领带做,但它可以复制)。@Shawn。您是否有使用OFFSET/FETCH
改进性能的参考资料?但它没有回答我的需要。我需要的是员工人数最多的项目。这里只给我每个项目的编号。@MikaAzulay。你运行过这个查询吗?它为项目提供了最多的员工。对于SQL Server,这将需要在FETCH
语句之前使用OFFSET 0行
。RE:。它将在TOP
上提供一些性能改进。(我不认为它能用领带做,但它可以复制)。@Shawn。您是否有关于使用OFFSET/FETCH
提高性能的参考?它说:“Pro\u works\u on.PNO”列在选择列表中无效,因为它未包含在聚合函数或GROUP BY子句中。仍然:“L.numOfEmployee”列在HAVING子句中无效,因为它未包含在聚合函数或GROUP BY子句中函数或GROUP BY子句。它表示:列“Pro_works_on.PNO”在选择列表中无效,因为它未包含在聚合函数或GROUP BY子句中。仍然:列“L.numOfEmployee”在HAVING子句中无效,因为它未包含在聚合函数或GROUP BY子句中。您使用哪种SQL你在用什么?这个错误看起来有点像MS SQL Server,但我不确定。或者MySQL,或者DB2。microsoft SQL management studioSQL只是许多供应商使用的一种语言。请具体说明您的dbms。它被称为SQL Server,因此添加t