如何使用“ max(count(*))”创建一个好的请求?

时间:2018-11-29 08:09:05

标签: sql oracle select count greatest-n-per-group

我不得不说谁是执行任务最多的科学家。我尝试了这段代码,但没有成功:

select name
from scientist, mission
where mission.nums = chercheur.nums
having count(*) = (select max(count(numis))  from mission, scientist where 
mission.nums = chercheur.nums
group by name)

我对此请求做了一些修改,但我只得到了错误(如果我没记错的话,ora-0095和ora-0096)。

此外,我用以下方法创建表:

CREATE TABLE Scientist
(NUMS NUMBER(8),
NAME VARCHAR2 (15),
CONSTRAINT CP_CHER PRIMARY KEY (NUMS));

CREATE TABLE MISSION
(NUMIS NUMBER(8),
Country VARCHAR2 (15),
NUMS NUMBER(8),
CONSTRAINT CP_MIS PRIMARY KEY (NUMIS),
CONSTRAINT CE_MIS FOREIGN KEY (NUMS) REFERENCES SCIENTIST (NUMC));

5 个答案:

答案 0 :(得分:2)

您可以计算每个科学家参与的任务,然后将该查询包装到带有窗口函数的查询中,该函数将根据参与者的参与程度对其进行排名:

echo var_dump($meta_value) . '</br>';

答案 1 :(得分:1)

第0步:格式化代码:-)它将使可视化变得容易得多

第1步:在任务表中按Nums来获取Numis计数。这将告诉您每个Nums完成了多少次任务

这是在cte块cnt_by_nums中完成的

下一步,通过将cnt_by_nums与科学家表连接起来,获得科学家的名字。

之后,您只想从cnt_by_num中获取具有cnt_by_missions作为最大可用值的科学家

with cnt_by_nums
  as (select Nums,count(Numis) as cnt_missions
          from mission
         group by Nums
      )
select a.Nums,max(b.Name) as name
  from cnt_by_nums a
  join scientist b
    on a.Nums=b.Nums 
group by a.Nums
having count(a.cnt_missions)=(select max(a1.cnt_missions) from cnt_by_nums a1)

答案 2 :(得分:1)

我会这样写一个查询:

SELECT NAME, COUNTER
FROM
(SELECT NAME, COUNT(*) AS COUNTER
FROM SCIENTIST S
LEFT JOIN MISSION M
ON S.NUMS=M.NUMS
GROUP BY NAME) NUM
INNER JOIN
(SELECT MAX(COUNTER) AS MAX_COUNTER FROM
(SELECT NAME, COUNT(*) AS COUNTER
FROM SCIENTIST S
LEFT JOIN MISSION M
ON S.NUMS=M.NUMS
GROUP BY NAME) C) MAX
ON NUM.COUNTER=MAX.MAX_COUNTER;

(它适用于MYSQL,希望在Oracle中也是如此)

答案 3 :(得分:0)

由于您无需选择科学家的姓名(仅计算他们的任务),因此无需在子查询中加入这些表。按外键分组就足够了:

select count(numis) from mission group by nums

您的列名有点奇怪,但这是您的选择;-)

可以通过两种方式仅选择任务参考最多的科学家。一种方法是您采用的方法,如果他们具有相同的最大任务,则可以聘请多名科学家。

查询中的第一个问题是您正在检查聚合(HAVING COUNT(*)=)而不进行分组。您只是将您的子选择分组。

第二,您不能聚合一个聚合(MAX(COUNT)),但是您只能选择该子选择的第一行,该行的大小按其大小排序,或者通过对子查询进行子查询来选择其最大值。

仅使用一行的方法:

select s.name from scientist s, mission m 
where m.nums = s.nums 
group by name 
having count(*) = 
    (select count(numis) from mission 
    group by nums 
    order by 1 desc 
    fetch first 1 row only)

使用双子查询的方法:

select s.name from scientist s, mission m 
where m.nums = s.nums 
group by name having count(*) = 
    (select max(numis) from 
        (select count(numis) numis from mission group by nums)
    )

第二种方法是根据您的最终结果进行第一次获取,但这将为您提供正好一位科学家,即使有多个具有相同最大任务的科学家也是如此:

select s.name from scientist s, mission m 
where m.nums = s.nums 
group by name
order by count(*) desc
fetch first 1 row only

使用笛卡尔积不是最新技术,但是优化器会将其与where子句中的给定引用进行“良好的联接”。

使用IBM Db2进行这些设置,但也可以在Oracle上使用。

答案 4 :(得分:0)

如果需要一行,那么在Oracle 12+中,您可以执行以下操作:

SELECT name, COUNT(*) AS cnt
FROM scientist s JOIN
     mission m
     ON s.nums = m.nums
GROUP BY name
ORDER BY COUNT(*) DESC
FETCH FIRST 1 ROW ONLY;

在早期版本中,通常会使用子查询:

SELECT s.*
FROM (SELECT name, COUNT(*) AS cnt
      FROM scientist s JOIN
           mission m
           ON s.nums = m.nums
      GROUP BY name
      ORDER BY COUNT(*) DESC
     ) sm
WHERE rownum = 1;

如果您想要联系,那么通常使用窗口函数是一个简单的解决方案:

SELECT s.*
FROM (SELECT name, COUNT(*) AS cnt,
             RANK() OVER (ORDER BY COUNT(*) DESC) as seqnum
      FROM scientist s JOIN
           mission m
           ON s.nums = m.nums
      GROUP BY name
      ORDER BY COUNT(*) DESC
     ) sm
WHERE seqnum = 1;