在MySQL中计算分组行数

74

我有一张名为xyz的表格,在其中有一行叫做components,以及一个称为labref的行,其中显示了labref编号。

表格xyz

labref             component
NDQA201303001          a
NDQA201303001          a
NDQA201303001          a
NDQA201303001          a
NDQA201303001          b
NDQA201303001          b
NDQA201303001          b
NDQA201303001          b
NDQA201303001          c
NDQA201303001          c
NDQA201303001          c
NDQA201303001          c

我想对组件进行分组,然后计算返回的行数等于3,我已经编写了以下SQL查询语句,但它不能帮助实现我的目标,反而为每个组件返回4。

SELECT DISTINCT component, COUNT( component ) 
FROM `xyz`
WHERE labref = 'NDQA201303001'
GROUP BY component

查询返回

表 xyz

labref         component   COUNT(component)       
NDQA201303001   a           4
NDQA201303001   b           4
NDQA201303001   c           4

我现在想要实现的是,从上述结果中计算行数并返回3作为行数,欢迎任何解决方法。


在这种情况下,你的意思是希望输出3吗? - Himanshu
1
xyz 中选择不同组件的计数。 - ATR
6个回答

150

3
当然,这是最佳解决方案,因为它不需要子查询。 - Meloman
1
最佳解决方案。这个方案应该被接受,因为它是更简单和更好的方法。 - Ayyaz Zafar
12
如果查询中没有使用"GROUP BY"语句,这个方法可以起作用。如果查询中有"GROUP BY"语句,则所有行都会显示1。 - Bala
2
@JohnySkovdal - 你制作了一个fiddle来回答不同的问题,因此说这个答案“不起作用”是不正确的。正如你的fiddle所显示的那样,这个答案正确地报告了不同值的数量。 - ToolmakerSteve
6
@JoelEnanodJr,Bala - 在这个答案中,您不需要使用“Group By”;这个答案是一种替代方法,在查询中不需要(也不能容忍)“Group By”。 OP只是试图使用“Group By”来获得他们需要的答案。将“Group By”与“Count(Distinct)”组合在一起没有意义;从查询中删除“Group By”。 - ToolmakerSteve
显示剩余6条评论

63

你需要做的是 -

SELECT
    COUNT(*)
FROM
    (
        SELECT
            DISTINCT component
        FROM
            `multiple_sample_assay_abc`
        WHERE
            labref = 'NDQA201303001'
    ) AS DerivedTableAlias

您也可以按照@hims056的建议这里所述,避免使用子查询。


@Kshitij - 当我们可以直接进行操作时,为什么要使用子查询呢? - Himanshu
2
hims056的解决方案更好 - 如果可以的话,避免使用子查询。 - fubo
11
在右括号后添加别名。 - Gene Kelly
2
这个答案之所以是正确的,是因为当你需要使用having子句时它才能工作。下面的答案依赖于能够重写查询而不使用having子句。 - Marlin Pierce
@MarlinPierce:只是好奇,可以告诉我一个你提到的场景的例子吗? - Himanshu
如果你想要所有labref值,但是筛选出count等于3的情况,那么问题就在于"WHERE labref = 'NDQA201303001'"这一部分。根据Kshitij的回答,你可以从子查询中删除WHERE子句,然后外部查询可以按照labref进行分组,并使用HAVING子句来筛选count等于3的值。 - Marlin Pierce

12
我找到了解决方案。 因此,如果您想计算组的数量而不是每个组中元素的数量,并将重复值返回到结果表中的每个组记录中,则应在您的计数函数上使用OVER()子句。 因此,例如上面的解决方案将是:
SELECT component, COUNT(*) OVER() as number_of_components FROM `xyz` 
WHERE labref = 'NDQA201303001' 
GROUP BY component

我想这适用于任何使用GROUP BY的查询,更多信息请查看上面的链接。

2
这是正确的做法。即使使用 limit x,也能正常工作。 - John C
1
请注意,您需要使用MySQL 8+才能使用OVER()(以及其他窗口函数)。 - Collin Krawll
没起作用。 - menoktaokan
@menoktaokan 检查你的 SQL 版本和查询语句。 - nojitsi

0

为什么不使用num_rows

如果您使用此方法,您无需以任何方式修改查询。

if ($result = $mysqli->query("SELECT DISTINCT component, COUNT( component ) 
    FROM `xyz`
    WHERE labref = 'NDQA201303001'
    GROUP BY component")){

    /* determine number of rows result set */
    $row_cnt = $result->num_rows;

    printf("Result set has %d rows.\n", $row_cnt);

    /* close result set */
    $result->close();
}

1
如果nest选择,则代码更短:select count(1) from ( ... ) t; 将产生任何查询的行数 [有一些限制,具体而言是内部查询不能有重复的列名],其中 "..." 是您正在计数的查询。为了提高性能,还可以将内部的 SELECT DISTINCT component, COUNT( component ) FROM 更改为 SELECT DISTINCT component FROM - ToolmakerSteve
值得注意的是,将一个大表带入PHP可能会超过PHP的内存限制并导致代码“致命错误”。为了节省内存,更好的方法是允许MySQL计算行数。 - Dawson Irvine
因为这会给你返回表中的总行数,而不是匹配查询条件的表中的总行数。尝试在一个有1000个结果的查询中添加limit 10 - John C

-1

还有:

SELECT `labref`, `component`, COUNT(*) as `count`
  FROM `xyz`
  WHERE labref = 'NDQA201303001'
  GROUP BY `component`;

应该返回:

labref component count
NDQA201303001 a 4
NDQA201303001 b 4
NDQA201303001 c 4

顺便说一下,没有子查询!

基于这个源


-2

选择 labref,component,Count(*) 作为计数从 xyz 分组按 labref,component


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接