在mySQL

时间:2018-10-28 02:43:19

标签: mysql sql

我有以下查询:

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_id和student_capacity行(但是允许使用联系,所以我不能仅将行限制为1)。 因此,在这种情况下,返回[160, 400, 12]

我该如何处理?我尝试将where num = max(num)放在代码后面,但这没用。一世 认为使用rank函数并限制rank = 1可能会有所帮助,但是我不确定应该在哪里实现。

3 个答案:

答案 0 :(得分:0)

如果您使用的是MySQL版本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)

答案 1 :(得分:0)

首先,我认为您不必要使用子选择查询(Derived Table)来获取当前结果。由于您没有对子查询结果做任何进一步的过滤;您可以取消子查询,仍然可以更有效地获得相同的结果:

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()功能(等级1是拥有最大便利设施的宿舍)。 Window functions仅在MySQL versions 8.0.2 and onwards中可用。

MySQL <8.0.2 版本中,我们可以利用User-defined variables进行计算。这种方法的基本要点是在“派生表”中以所需顺序获取结果集。在这种情况下,我们关注排名最高的宿舍;因此我们以num的降序获得结果集。

现在,我们利用两个会话变量在Select子句中存储先前的行值,以便确定当前的行值。我们基本上存储了前一行的ranknum值;并且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

答案 2 :(得分:0)

诸如MAX,MIN,AVE等集合函数属于查询的select部分,而不属于where。此外,您不能嵌套聚合函数,因此Max(Count *))将不起作用。但是,您可以嵌套选择,从而以这种方式嵌套聚合函数。以下示例摘自OMG Ponies的类似文章:Can I do a max(count(*)) in SQL

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

对于像您这样简单而又初级的查询,我会推荐这种方法,因为它比较简单,但是Madhur的回答和您使用Rank的直觉也很完美。