【问题标题】:How to fix a count() in a query with a "group by" clause?如何使用“group by”子句修复查询中的 count()?
【发布时间】:2012-11-13 19:50:11
【问题描述】:

我有一个函数,它获取一个 SQL 代码并在其中插入一个计数字段并执行查询以返回其中的行数。目标是拥有一个动态 SQL 代码,并且无论它有什么代码都能够获得它的记录数,因为我在注册表过滤器窗口中使用它,我永远不知道可能会生成什么代码,因为用户可以添加尽可能多的代码根据他/她的需要过滤。

但是当我使用group by 子句时,结果是错误的,因为它正在计算主注册表出现的次数,因为在许多join 连接上使用。

上面代码的结果应该只有一行,其列的结果为10,但我得到一个新表,第一列的第一列是2,另一行是1行。

如果我取消group by 子句,我将收到11 作为计数结果,但第一行将被计算两次。

我应该怎么做才能获得单行和正确的数字?

SELECT 
 COUNT(*) QUERYRECORDCOUNT, // this line appears only in the Count() function 
 ARTISTA.*,
 CATEGORIA.NOME AS CATEGORIA,
 ATIVIDADE.NOME AS ATIVIDADE,
 LOCALIDADE.NOME AS CIDADE,
 MATRICULA.NUMERO AS MAP

FROM
 ARTISTA
 LEFT JOIN PERFIL ON PERFIL.REGISTRO = ARTISTA.ARTISTA_ID
 LEFT JOIN CATEGORIA ON CATEGORIA.CATEGORIA_ID = PERFIL.CATEGORIA
 LEFT JOIN ATIVIDADE ON ATIVIDADE.ATIVIDADE_ID = PERFIL.ATIVIDADE
 LEFT JOIN LOCALIDADE ON LOCALIDADE.LOCALIDADE_ID = ARTISTA.LOCAL_ATIV_CIDADE
 LEFT JOIN MATRICULA ON MATRICULA.REGISTRO = ARTISTA.ARTISTA_ID

WHERE 
 ((ARTISTA.SIT_PERFIL <> 'NORMAL') AND (ARTISTA.SIT_PERFIL <> 'PRIVADO'))
GROUP BY
 ARTISTA.ARTISTA_ID
ORDER BY 
 ARTISTA.ARTISTA_ID;

【问题讨论】:

  • 如果你总是 LEFT JOIN,你可以简单地选择COUNT(*) FROM ARTISTA WHERE...而不选择额外的行和额外的连接。
  • 问题是我的函数将接收带有任意数量字段的 SQL 代码并加入,它必须更改 SQL 以将“计数”放在与结果相同的方式是原封不动的时候。

标签: mysql sql delphi zeos


【解决方案1】:

这始终为您提供任何查询的行数:

Select count(*) as rowcount from
(

     Paste your query here

) as countquery

【讨论】:

  • 效率不如你建议使用COUNT(DISTINCT ARTISTA.ARTISTA_ID) 并删除所有连接。在这种情况下 - 以适当的方式重写查询是有意义的,而不仅仅是盲目地用您提出的内容包装它。所以,我个人不会推荐你的解决方案
  • 当然,您可以为此重写查询。只需添加 count(*) 并删除 group by。我只是提供了一个应该始终有效的解决方案,如果您只想知道将获得多少条记录,则不需要您重写查询。
  • "并且如果您只想知道将获得多少条记录,则不需要您重写查询" ---而且效率非常低。没有理由留下不影响结果的查询部分。
  • 嗯,它可能非常低效。事实证明,做点什么。在那之前,我们谈论的是过早优化。
  • 实际上并非如此。在那之前,我们谈论的是没有意义的查询。这不是优化,而是关于您要查询的内容。如果不需要,为什么要LEFT JOIN?您是否还在代码中为查询添加一些随机片段只是为了好玩?
【解决方案2】:

由于您是按ARTISTA.ARTISTA_ID 分组,COUNT(*) QUERYRECORDCOUNT 将返回每个ARTISTA.ARTISTA_ID 值的记录数。

如果你想要全局计数,那么你需要使用嵌套查询:

SELECT COUNT(*) AS QUERYRECORDCOUNT 
    FROM (SELECT 
     ARTISTA.*,
     CATEGORIA.NOME AS CATEGORIA,
     ATIVIDADE.NOME AS ATIVIDADE,
     LOCALIDADE.NOME AS CIDADE,
     MATRICULA.NUMERO AS MAP

    FROM
     ARTISTA
     LEFT JOIN PERFIL ON PERFIL.REGISTRO = ARTISTA.ARTISTA_ID
     LEFT JOIN CATEGORIA ON CATEGORIA.CATEGORIA_ID = PERFIL.CATEGORIA
     LEFT JOIN ATIVIDADE ON ATIVIDADE.ATIVIDADE_ID = PERFIL.ATIVIDADE
     LEFT JOIN LOCALIDADE ON LOCALIDADE.LOCALIDADE_ID = ARTISTA.LOCAL_ATIV_CIDADE
     LEFT JOIN MATRICULA ON MATRICULA.REGISTRO = ARTISTA.ARTISTA_ID

    WHERE 
     ((ARTISTA.SIT_PERFIL <> 'NORMAL') AND (ARTISTA.SIT_PERFIL <> 'PRIVADO'))
    GROUP BY
     ARTISTA.ARTISTA_ID
    ORDER BY 
     ARTISTA.ARTISTA_ID);

在这种情况下,您可能不需要选择那么多列。

如果您需要检索带有详细信息的所有记录计数,那么最好使用两个单独的查询。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-22
    • 1970-01-01
    • 1970-01-01
    • 2013-09-22
    • 2021-12-22
    • 2021-12-19
    • 2016-05-09
    相关资源
    最近更新 更多