在mysql中返回具有最大值(多个)的行

0pizxfdo  于 2021-06-18  发布在  Mysql
关注(0)|答案(3)|浏览(335)

我有以下疑问:

select
    a.dormid, a.student_capacity, count(*) as num
from
    (select
       d.dormid, 
       d.dorm_name, 
       d.student_capacity, 
       h.amenid
     from
       (Dorm d left join Has_amenity h 
       on d.dormid=h.dormid)
    ) a
group by a.dormid, a.student_capacity

结果如下:

+--------+------------------+-----+
| dormid | student_capacity | num |
+--------+------------------+-----+
|    109 |              128 |   8 |
|    104 |              256 |   3 |
|    160 |              400 |  12 |
|    100 |               85 |   5 |
|    117 |               40 |   1 |
|    110 |              116 |   5 |
|    140 |              355 |   6 |
+--------+------------------+-----+

我只想得到最大值为'num'的dorm\u id和student\u capacity行(但是考虑到关系,所以我不能将行限制为1)。所以在这种情况下,返回 [160, 400, 12] .
我该如何处理这个问题?我试着把 where num = max(num) 但那没用。我认为使用 rank 函数和限制rank=1可能会有所帮助,但我不确定应该在哪里实现它。

lqfhib0f

lqfhib0f1#

诸如max、min、ave等聚合函数属于查询的select部分,而不是where。此外,不能嵌套聚合函数,因此max(count*)将不起作用。但是,您可以嵌套selects,从而以这种方式嵌套聚合函数。下面的例子来自omg ponies在这里的一篇类似文章:我可以在sql中执行max(count(*)吗

SELECT MAX(y.num) FROM 
    (SELECT COUNT(*) AS num FROM TABLE x) y

对于像你这样简单的初学者,我推荐这种方法,因为它更简单,但是madhur的答案和你使用rank work的本能也很好。

osh3o9ms

osh3o9ms2#

如果您使用的是mysql verison 8,那么您可以尝试使用with子句:

WITH
counts AS (select dorm_id,count(*) as num from Dorm)
select dormid, dorm_capacity,count(*) 
from Dorm 
having count(*)=(select max(num) from counts)
68de4m5k

68de4m5k3#

首先也是最重要的一点,我认为您不必要地使用子选择查询(派生表)来获取当前结果。因为您没有对子查询结果进行任何进一步的过滤;您可以去掉子查询,仍然可以更有效地获得相同的结果:

SELECT 
 d.dormid, 
 d.student_capacity, 
 COUNT(d.dormid) AS num 
FROM Dorm AS d 
LEFT JOIN Has_amenity AS h 
 ON h.dormid = d.dormid 
GROUP BY d.dormid, d.student_capacity

现在,你基本上需要 Dense_Rank() 功能性(排名第一的宿舍设施最多)。窗口函数仅在mysql 8.0.2及更高版本中可用。
在mysql<8.0.2的版本中,我们可以使用用户定义的变量来计算相同的值。这种方法的基本要点是在派生表中按所需顺序获取结果集。在这种情况下,我们关心的是排名最高的宿舍;所以我们得到结果集的降序 num .
现在,我们使用两个会话变量来存储前面的行值,以便在 Select 条款。我们基本上存储前一行 rank 以及 num 价值观;以及 if 当前行的 num 值与前一行不同,我们增加 rank .
最后,再次使用这个结果作为派生表,我们只需要考虑 rank = 1 (使用 Where 条款。)
尝试以下查询(适用于所有mysql版本):

SELECT dt2.*
FROM 
(
  SELECT 
    dt.dormid, 
    dt.student_capacity, 
    @drank := IF(@n <> dt.num, @drank + 1, @drank) AS rank, 
    @n := dt.num AS num 
  FROM   
  (
    SELECT 
     d.dormid, 
     d.student_capacity, 
     COUNT(d.dormid) AS num 
    FROM Dorm AS d 
    LEFT JOIN Has_amenity AS h 
     ON h.dormid = d.dormid 
    GROUP BY d.dormid, d.student_capacity 
    ORDER BY num DESC 
  ) AS dt 
  CROSS JOIN (SELECT @drank := 0, 
                     @n := 0) AS user_init_vars 
) AS dt2 
WHERE dt2.rank = 1

相关问题