【问题标题】:In SQL, what's the difference between count(column) and count(*)?在 SQL 中,count(column) 和 count(*) 有什么区别?
【发布时间】:2010-09-08 17:26:47
【问题描述】:

我有以下疑问:

select column_name, count(column_name)
from table
group by column_name
having count(column_name) > 1;

如果我将所有对count(column_name) 的调用替换为count(*),会有什么不同?

这个问题的灵感来自How do I find duplicate values in a table in Oracle?


为了澄清已接受的答案(也许是我的问题),将count(column_name) 替换为count(*) 将在结果中返回一个额外的行,其中包含null 和列中null 值的计数。

【问题讨论】:

    标签: sql


    【解决方案1】:

    count(*) 计算 NULL 而count(column) 不计算

    [edit] 添加此代码以便人们可以运行它

    create table #bla(id int,id2 int)
    insert #bla values(null,null)
    insert #bla values(1,null)
    insert #bla values(null,1)
    insert #bla values(1,null)
    insert #bla values(null,1)
    insert #bla values(1,null)
    insert #bla values(null,null)
    
    select count(*),count(id),count(id2)
    from #bla
    

    结果 7 3 2

    【讨论】:

    • 只是好奇:如果你有一行 all NULL,count(*) 是否仍然计算它,或者只是 count(column) 用于所有列?
    • 这个标准是否适用于 DBMS?
    • 值得一提的是,如果你有一个不可为空的列,例如 ID,那么 count(ID) 将比 count(*) 显着提高性能。
    • @tsilb:@Alan 发布的答案指出“count(*) 是通过查看相关表上的索引而不是实际数据行来计算的”,如果为真,则您的评论无效.我很欣赏@Alan 可能是错误的,但我对您的信息来源很感兴趣,以便找出正确的信息。
    • @tsilb:许多现代查询优化器会优化 count(*) 以在有意义的时候使用索引。
    【解决方案2】:

    使用 * 和特定列之间的另一个小区别是,在列的情况下,您可以添加关键字 DISTINCT,并将计数限制为不同的值:

    select column_a, count(distinct column_b)
    from table
    group by column_a
    having count(distinct column_b) > 1;
    

    【讨论】:

    • 按列分组和被计数的应该不同吗?否则你不会从这个查询中得到任何东西
    • 是的,对不起.. 我没有注意到它们在示例中是同一列。我会更新帖子。
    • 代码毫无用处。 select column_a, count(distinct column_a) from table group by column_a having count(distinct column_a) > 1; 让它变得有意义。
    【解决方案3】:

    另一个可能是微妙的区别是,在某些数据库实现中,count(*) 是通过查看相关表上的索引而不是实际数据行来计算的。由于没有指定特定的列,因此无需担心实际的行及其值(如果您计算了特定的列,就会出现这种情况)。允许数据库使用索引数据比计算“真实”行要快得多。

    【讨论】:

    • +1 是的,对于 Oracle 和从 9.2 开始的 PostgreSQL 来说当然是这样。
    • @DavidAldridge 您能否提供一个指向文档(尤其是对于 postgresql)的指针?谢谢。
    【解决方案4】:

    docs 中的解释有助于解释这一点:

    COUNT(*) 返回组中的项目数,包括 NULL 值和重复项。

    COUNT(expression) 计算组中每一行的表达式并返回非空值的数量。

    所以 count(*) 包含空值,其他方法不包含。

    【讨论】:

    • 对于 SQL 新手:您指的是什么帮助文件?
    【解决方案5】:

    我们可以使用Stack Exchange Data Explorer 通过一个简单的查询来说明区别。 Stack Overflow 数据库中的 Users 表中的列通常为空,例如用户的网站 URL。

    -- count(column_name) vs. count(*)
    -- Illustrates the difference between counting a column
    -- that can hold null values, a  'not null' column, and  count(*)
    
    select count(WebsiteUrl), count(Id), count(*) from Users
    

    如果您在Data Explorer 中运行上述查询,您将看到count(Id)count(*) 的计数相同,因为Id 列不允许null 值。不过,WebsiteUrl 计数要低得多,因为该列允许 null

    【讨论】:

      【解决方案6】:

      COUNT(*) – 返回表中的记录总数(包括 NULL 值记录)。

      COUNT(Column Name) – 返回非​​ NULL 记录的总数。这意味着,它忽略了计算该特定列中的 NULL 值记录。

      【讨论】:

        【解决方案7】:

        基本上COUNT(*) 函数会返回表中的所有行,而COUNT(COLUMN_NAME) 不会;也就是说,它排除了这里的每个人也在这里回答的空值。 但最有趣的部分是优化查询和数据库,最好使用COUNT(*),除非进行多次计数或复杂查询,而不是COUNT(COLUMN_NAME)。否则,在处理大量数据时,它确实会降低您的数据库性能。

        【讨论】:

          【解决方案8】:
          • COUNT(*) 语句指示 SQL Server 返回表中的所有行,包括 NULL。
          • COUNT(column_name) 只检索行上具有非空值的行。

          请参阅以下代码以执行 SQL Server 2008:

          -- Variable table
          DECLARE @Table TABLE
          (
                CustomerId int NULL 
              , Name nvarchar(50) NULL
          )
          
          -- Insert some records for tests
          INSERT INTO @Table VALUES( NULL, 'Pedro')
          INSERT INTO @Table VALUES( 1, 'Juan')
          INSERT INTO @Table VALUES( 2, 'Pablo')
          INSERT INTO @Table VALUES( 3, 'Marcelo')
          INSERT INTO @Table VALUES( NULL, 'Leonardo')
          INSERT INTO @Table VALUES( 4, 'Ignacio')
          
          -- Get all the collumns by indicating *
          SELECT  COUNT(*) AS 'AllRowsCount'
          FROM    @Table
          
          -- Get only content columns ( exluce NULLs )
          SELECT  COUNT(CustomerId) AS 'OnlyNotNullCounts'
          FROM    @Table
          

          【讨论】:

            【解决方案9】:

            进一步阐述@SQLMeance 和@Brannon 使用GROUP BY 子句给出的答案,该子句已被OP 提及但@SQLMenace 的答案中没有出现

            CREATE TABLE table1 ( 
            id INT 
            );
            
            INSERT INTO table1 VALUES 
            (1), 
            (2), 
            (NULL), 
            (2), 
            (NULL), 
            (3), 
            (1), 
            (4), 
            (NULL), 
            (2);
            
            SELECT * FROM table1;
            
            +------+
            | id   |
            +------+
            |    1 |
            |    2 |
            | NULL |
            |    2 |
            | NULL |
            |    3 |
            |    1 |
            |    4 |
            | NULL |
            |    2 |
            +------+
            10 rows in set (0.00 sec)
            
            SELECT id, COUNT(*) FROM table1 GROUP BY id;
            
            +------+----------+
            | id   | COUNT(*) |
            +------+----------+
            |    1 |        2 |
            |    2 |        3 |
            | NULL |        3 |
            |    3 |        1 |
            |    4 |        1 |
            +------+----------+
            5 rows in set (0.00 sec)
            

            这里,COUNT(*) 统计每种类型的id 的出现次数,包括NULL

            SELECT id, COUNT(id) FROM table1 GROUP BY id;
            
            +------+-----------+
            | id   | COUNT(id) |
            +------+-----------+
            |    1 |         2 |
            |    2 |         3 |
            | NULL |         0 |
            |    3 |         1 |
            |    4 |         1 |
            +------+-----------+
            5 rows in set (0.00 sec)
            

            这里COUNT(id)统计id每种类型的出现次数,但不统计NULL的出现次数

            SELECT id, COUNT(DISTINCT id) FROM table1 GROUP BY id;
            
            +------+--------------------+
            | id   | COUNT(DISTINCT id) |
            +------+--------------------+
            | NULL |                  0 |
            |    1 |                  1 |
            |    2 |                  1 |
            |    3 |                  1 |
            |    4 |                  1 |
            +------+--------------------+
            5 rows in set (0.00 sec)
            

            这里COUNT(DISTINCT id)只统计id每种类型的出现次数(不计算重复),也不统计NULL的出现次数

            【讨论】:

              【解决方案10】:

              最好用

              Count(1) in place of column name or * 
              

              计算表中的行数,它比任何格式都快,因为它永远不会检查表中的列名是否存在

              【讨论】:

              • 至少对于 Oracle 不正确,我怀疑对于其他 RDBMS 也是如此。在内部,count(1) 被转换为 count(*)。特别是,count(*) 的性能不会受到行大小的负面影响,这是一个常见的误解。
              • 这适用于 SQL Server。正如@Ali Adravi 所说,COUNT(*)COUNT(columnName) 相比不会检查列值,因为它只是枚举行。但是COUNT(columnName) 甚至在id 列上应用的count 也更慢!当然,至少在 SQL Server 中是这样。
              【解决方案11】:

              如果您的表中固定一列,则没有区别,如果您想使用多于一列,则必须指定需要计算多少列......

              谢谢,

              【讨论】:

                【解决方案12】:

                如前面的答案中所述,Count(*) 甚至会计算 NULL 列,而 count(Columnname) 仅在列具有值时才计算在内。

                最好避免*Select *count *,...)

                【讨论】:

                • 完全避免COUNT(*)
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2010-09-08
                • 2015-03-03
                • 2011-02-22
                • 2020-03-02
                • 1970-01-01
                • 2020-11-10
                相关资源
                最近更新 更多