如何从计数中选择具有最大产生值的行

Posted

技术标签:

【中文标题】如何从计数中选择具有最大产生值的行【英文标题】:How to select a row with the maximum produced value from count 【发布时间】:2012-11-24 19:26:00 【问题描述】:

我对 mysql 有点陌生,所以我被困在一个查询上。 我从一个名为歌曲的数据库中获得了这张表(我只能在这个数据库中读取):

table name:cd_production

code_cd  etaireia  etos
______________________
400400  ODEON     1987
400401  ODEON     1986
400412  COLUMBIA  1990
400420  COLUMBIA  1990
400657  LYRA      1965
410000  COLUMBIA  1962
410001  COLUMBIA  1964
410003  PHILIPS   1979
410005  PHILIPS   1971
420430  ODEON     2002
420440  LYRA      2005
420450  COLUMBIA  2009
420460  ODEON     2007
420470  PHILIPS   2008
420480  ODEON     2002
420490  COLUMBIA  2010
500500  SONY      1968
500510  SONY      1972
600601  COLUMBIA  1962
600602  COLUMBIA  1963
600603  ODEON     1964
670670  PHILIPS   1983

并且我想找到产生的 cd 数量最多的 etaireia(意味着每个 etaireia 的 code_cd 不同)。 请问

select etaireia ,count(all code_cd) as cds
from cd_production
group by etaireia

我得到一个返回列的列表

etaireia  cds
________________    
COLUMBIA   8
LYRA       2
ODEON      6
PHILIPS    4
SONY       2

这有点正确,但我不知道如何只获得具有最大 cd 的 etaireia,例如

    etaireia  cds
    ________________    
    COLUMBIA   8

这里有什么诀窍? 我不想使用 LIMIT 1 方法,因为它不是通用的。 提前致谢

【问题讨论】:

如果您有多个具有相同最大计数的行,是否要检索所有行? @MichaelBerkowski 是的,我想要 :) 好的,我更新了答案。 【参考方案1】:

如果您希望找到所有记录及其计数最大的计数,您可以在HAVING 子句中使用子查询来确定COUNT()MAX() 值是多少。

SELECT 
  etaireia,
  COUNT(*) AS cds
FROM
  cd_production
GROUP BY etaireia
HAVING cds = (
   SELECT MAX(cds) 
   FROM (SELECT etaireia, COUNT(*) as cds
         FROM cd_production 
         GROUP BY etaireia) subq
   )

http://sqlfiddle.com/#!2/869b4/4

限制为单行的方法因 RDBMS 而异。 MySQL 使用LIMIT,MSSQL 使用TOP,Oracle 使用ROWNUM...使用RDBMS 特定的方法使这变得简单很多,因为您不需要在HAVING 子句中嵌套子查询。相反,您可以在HAVING 子查询中使用LIMIT 来仅返回一个最大的COUNT(),而无需包装另一个查询以获取MAX()

SELECT 
  etaireia,
  COUNT(*) AS cds
FROM
  cd_production
GROUP BY etaireia
HAVING cds = (
   SELECT COUNT(*)
   FROM cd_production 
   GROUP BY etaireia
   ORDER BY COUNT(*) DESC 
   LIMIT 1
)

and here is the MySQL-specific version...

【讨论】:

对不起,我注意到我不想使用 limit 1 方法导致其错误。如果多个原始数据具有相同的最大值怎么办?它不起作用。 打破名称的关系。但它会产生复杂的查询。 @michael berkowski 我不明白。它不起作用。该查询假定 cd 已存在于表中,但事实并非如此。 cds 列是输出 我认为它的错误用法。 have 仅应用于查询的输出,而不是在服务器中。 @GeoPapas HAVING 在聚合之后应用,因此在 COUNT(*) 之后但仍在服务器上,而不是您的应用程序代码上。它确实 工作,如 SQLFiddle 链接中所示。你是什​​么意思它假设CD已经存在?无论表中有多少,该值都是正确的。通过从 SQLFiddle 的示例中删除行进行测试。例如:sqlfiddle.com/#!2/b1f37/1【参考方案2】:

应该在大多数 DBMS 中运行的其他“通用”方式(并且不要使用 MYSQL 特定的LIMIT 关键字):

SELECT 
    etaireia,
    COUNT(*) AS cds
FROM
    cd_production c
GROUP BY 
    etaireia
HAVING 
    COUNT(*) >= ALL 
        ( SELECT COUNT(*) 
          FROM cd_production cc
          GROUP BY cc.etaireia
        ) ; 

还有这个:

SELECT 
    etaireia,
    COUNT(*) AS cds
FROM
    cd_production  c
GROUP BY 
    etaireia
HAVING 
    NOT EXISTS
        ( SELECT * 
          FROM cd_production  cc
          GROUP BY cc.etaireia
          HAVING COUNT(*) > COUNT(DISTINCT c.code_cd)
        ) ; 

都在 SQL-Fiddle 中测试:test-1(适用于所有 4 个:Postgres、SQL-Server、Oracle、MySQL,除了不在 Postgres 中运行的第二个查询)。


对于那些具有窗口函数(和OVER 子句)的 DBMS,还有另一种方法(适用于 Postgres、Oracle、SQL-Server 2012):

SELECT etaireia, cds
FROM
  ( SELECT 
        etaireia, cds,
        RANK() OVER (ORDER BY cds DESC) AS rnk
    FROM
      ( SELECT 
            etaireia,
            COUNT(*) AS cds 
        FROM
            cd_production  c
        GROUP BY 
            etaireia
      ) tmp
  ) tmp2
WHERE rnk = 1 ;

以下是“标准”方式。它应该在支持标准 SQL 语法 FETCH ... OFFSET(相当于供应商特定的 LIMITTOP)的 Postgres 和 SQL-Server 中工作:

SELECT 
    etaireia,
    COUNT(*) AS cds
FROM
    cd_production AS c
GROUP BY 
    etaireia
ORDER BY
    cds DESC
OFFSET 0 ROWS
FETCH FIRST 1 ROWS ONLY ;

都在 SQL-Fiddle 中测试:test-3(Q4 在 Postgres 和 SQL-Server 2012 中工作)。 请注意,这将给出与前 3 个查询不同的结果,因为 FETCH 语法不解析平局,只返回平局中的一行。

【讨论】:

【参考方案3】:

那么只选择第一个:

select Top 1 etaireia ,count(all code_cd) as cds
from cd_production
group by etaireia

忽略,因为你不想使用限制。

【讨论】:

似乎不适用于“Top”关键字。 :(也许它不被数据库支持 mysql 不使用TOP,除此之外与使用LIMIT 的意图相同,OP 要求不要使用它

以上是关于如何从计数中选择具有最大产生值的行的主要内容,如果未能解决你的问题,请参考以下文章

如何从Oracle中的另一个子查询中选择具有最大列的行

如何提高 SQL Server 查询的性能以选择具有值的行不在子查询中的一次计数

mysql返回最大n个具有相同值的行

具有最大值和最小值的 jQuery 计数器

从Oracle SQL中的每个组中选择具有最大值的行[重复]

如何选择最大日期早于某个值的行