为什么COUNT()只显示一行表?

时间:2016-09-12 07:01:39

标签: mysql sql database count mysql-5.7

我在数据库pet中有以下表menagerie

+--------+-------------+---------+------+------------+------------+
| name   | owner       | species | sex  | birth      | death      |
+--------+-------------+---------+------+------------+------------+
| Tommy  | Salman Khan | Lebre   | NULL | 1999-01-13 | 0000-00-00 |
| Bowser | Diane       | dog     | m    | 1981-08-31 | 1995-07-29 |
+--------+-------------+---------+------+------------+------------+

现在如果我运行以下查询:

select owner, curdate() from pet;  

我得到以下输出:

+-------------+------------+
| owner       | curdate()  |
+-------------+------------+
| Salman Khan | 2016-09-12 |
| Diane       | 2016-09-12 |
+-------------+------------+

输出显示owner的所有值,以及每行curdate()返回的值。

现在,如果我运行以下查询:

select owner, count(*) from pet;  

我得到以下输出:

+-------------+----------+
| owner       | count(*) |
+-------------+----------+
| Salman Khan |        2 |
+-------------+----------+  

我的问题是curdate()count()函数之间的区别是什么让MySQL输出第一个owner Diane 示例

7 个答案:

答案 0 :(得分:56)

COUNT()是一个聚合函数,通常与GROUP BY子句结合使用。

curdate()是一个输出当前日期的日期函数。

只有MySQL(据我所知)在不使用GROUP BY子句的情况下允许使用此语法。由于您没有提供,COUNT(*)将计算表格中的总行数,owner列将随机选择/优化程序默认/索引。

这应该是您的查询:

select owner, count(*) 
from pet
group by owner;

告诉优化器计算总行数,每个所有者。

当没有提到group by子句时 - 聚合函数应用于表的整个数据。

编辑:对每行应用的计数通常不会使用COUNT()完成,并且通常与分析函数一起使用 - >遗憾的是,COUNT() OVER(PARTITION...)在MySQL中并不存在。您的另一个选择是为此附加列生成JOIN/CORRELATED QUERY

另一个编辑:如果您希望每个所有者旁边的总计数,您可以使用子查询:

SELECT owner,
       (SELECT COUNT(*) FROM pet) as cnt
FROM pet

答案 1 :(得分:8)

这看起来与本页底部的方案完全相同:MySQL Documentation: 4.3.4.8 Counting Rows

  

如果未启用ONLY_FULL_GROUP_BY,则处理查询   将所有行视为一个组,但为每个组选择的值   命名列是不确定的。服务器可以自由选择值   从任何一行:

mysql> SET sql_mode = '';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT owner, COUNT(*) FROM pet;
+--------+----------+
| owner  | COUNT(*) |
+--------+----------+
| Harold |        8 |
+--------+----------+
1 row in set (0.00 sec)

我想在这种情况下only_full_group_by未设置。

答案 2 :(得分:4)

只有MySQL才能让你进行这种查询。

您应始终在GROUP BY子句中指定未与聚合函数组合的所有列。如果没有,数据将合并为1行,聚合列设置正确,所有其他列随机或使用索引选择。

所以你需要这个:

SELECT owner, count(*) FROM pet GROUP BY owner;

将导致:

Saknan Khan |  1
Diane       |  1

这是你打算实现的目标吗?

或许你试过这样做:

SELECT t.owner,
       COUNT(*) as cnt
FROM pet t
CROSS JOIN pet s
GROUP BY t.owner

这会产生一个额外的列,其中包含每个所有者旁边的总计数。

答案 3 :(得分:2)

大多数DBMS系统不允许像count()这样的聚合函数以及没有group by的其他列;因为某种原因。 DBMS不知道要分组的列: - )。

解决方案是按所有者列对查询进行分组,如下所示:

SELECT owner, count(*) FROM pet GROUP BY owner;

答案 4 :(得分:2)

计数(*)聚合函数它只返回一个值,即总行数。而 curdate()功能只是提供系统的当前日期。

答案 5 :(得分:2)

最后一个查询对Oracle无效:ORA-00937:不是单组函数。这意味着您需要GROUP BY子句。您在MySql实现中发现了一个漏洞。不要在生产系统中依赖这样的查询,在下一版本的MySql中,这可能不起作用。

答案 6 :(得分:0)

是的,这通常不使用group by子句。

http://www.w3schools.com/sql/sql_groupby.asp您应该在链接中阅读有关group by子句的所有信息。

所有列都应该被提及聚合或分组