Trong SQL, sự khác biệt giữa đếm (cột) và đếm (*) là gì?


204

Tôi có câu hỏi sau:

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

Điều gì sẽ là sự khác biệt nếu tôi thay thế tất cả các cuộc gọi count(column_name)đến count(*)?

Câu hỏi này được lấy cảm hứng từ Làm thế nào để tôi tìm thấy các giá trị trùng lặp trong một bảng trong Oracle? .


Để làm rõ câu trả lời được chấp nhận (và có thể là câu hỏi của tôi), thay thế count(column_name)bằng count(*)sẽ trả về một hàng thừa trong kết quả có chứa a nullvà số lượng nullgiá trị trong cột.

Câu trả lời:


234

count(*)đếm NULL và count(column)không

[sửa] đã thêm mã này để mọi người có thể chạy nó

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

kết quả 7 3 2


8
Chỉ tò mò: nếu bạn có một hàng với tất cả các NULL, thì tính (*) vẫn sẽ tính nó hay chỉ là đếm (cột) cho tất cả các cột?
Joel Coehoorn

7
Là tiêu chuẩn này trên DBMS?
Nhật thực

51
Điều đáng nói là nếu bạn có một cột không thể rỗng như ID, thì số đếm (ID) sẽ cải thiện đáng kể hiệu suất so với số lượng (*).
tsilb

12
@tsilb: Câu trả lời được đăng bởi @Alan nói rằng "tính (*) được tính bằng cách xem các chỉ mục trên bảng được đề cập thay vì các hàng dữ liệu thực tế", nếu đúng, sẽ làm mất hiệu lực nhận xét của bạn. Tôi đánh giá cao rằng @Alan có thể sai nhưng tôi quan tâm đến nguồn thông tin của bạn để tìm ra thông tin nào là đúng.
Tony

12
@tsilb: Nhiều trình tối ưu hóa truy vấn hiện đại sẽ tối ưu hóa số lượng (*) để sử dụng các chỉ mục khi có ý nghĩa.
Shannon Severance

37

Một điểm khác biệt nhỏ, giữa việc sử dụng * và một cột cụ thể là trong trường hợp cột bạn có thể thêm từ khóa DISTINCT và hạn chế số đếm thành các giá trị riêng biệt:

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

1
Nhóm theo cột và nhóm được tính có khác nhau không? nếu không, bạn sẽ không nhận được gì từ truy vấn này
steevc

Vâng, xin lỗi .. tôi đã không nhận thấy rằng chúng là cùng một cột trong ví dụ. Tôi sẽ cập nhật bài viết.
Brannon

16

Một sự khác biệt nữa và có lẽ tinh tế là trong một số triển khai cơ sở dữ liệu, số đếm (*) được tính bằng cách xem các chỉ mục trên bảng được đề cập thay vì các hàng dữ liệu thực tế. Vì không có cột cụ thể nào được chỉ định, nên không cần bận tâm đến các hàng thực tế và giá trị của chúng (như sẽ có nếu bạn tính một cột cụ thể). Cho phép cơ sở dữ liệu sử dụng dữ liệu chỉ mục có thể nhanh hơn đáng kể so với việc làm cho nó đếm các hàng "thực".


5
+1 Có, chắc chắn đúng với Oracle và cho PostgreSQL từ 9.2 trở đi.
David Aldridge

@DavidAldridge Bạn có thể cung cấp một con trỏ tới tài liệu (đặc biệt là cho postgresql) trong đó điều này được đề cập? Cảm ơn.
Bhushan


10

Giải thích trong các tài liệu , giúp giải thích điều này:

COUNT (*) trả về số lượng mục trong một nhóm, bao gồm các giá trị NULL và các mục trùng lặp.

COUNT (biểu thức) đánh giá biểu thức cho mỗi hàng trong một nhóm và trả về số lượng giá trị không có giá trị.

Vì vậy, đếm (*) bao gồm null, phương thức khác thì không.


Đối với newbs SQL: Bạn đang đề cập đến tệp trợ giúp nào?
Bill Lizard

10

Chúng ta có thể sử dụng Stack Exchange Data Explorer để minh họa sự khác biệt bằng một truy vấn đơn giản. Bảng Người dùng trong cơ sở dữ liệu của Stack Overflow có các cột thường bị bỏ trống, như URL Trang web của người dùng.

-- 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

Nếu bạn chạy truy vấn ở trên trong Data Explorer , bạn sẽ thấy số đếm giống nhau count(Id)count(*)Idcột không cho phép nullcác giá trị. Số WebsiteUrllượng thấp hơn nhiều, mặc dù, bởi vì cột đó cho phép null.


2

Về cơ bản, COUNT(*)hàm trả về tất cả các hàng từ một bảng trong khi COUNT(COLUMN_NAME)không; đó là loại trừ các giá trị null mà mọi người ở đây cũng đã trả lời ở đây. Nhưng phần thú vị nhất là làm cho các truy vấn và cơ sở dữ liệu được tối ưu hóa, tốt hơn là sử dụng COUNT(*)trừ khi thực hiện nhiều lần đếm hoặc một truy vấn phức tạp hơn là COUNT(COLUMN_NAME). Mặt khác, nó thực sự sẽ làm giảm hiệu suất DB của bạn trong khi xử lý một số lượng lớn dữ liệu.


1
  • Câu COUNT (*) cho biết SQL Server trả về tất cả các hàng từ một bảng, bao gồm cả NULL.
  • COUNT (cột_name) chỉ lấy các hàng có giá trị khác null trên các hàng.

Vui lòng xem đoạn mã sau để thực hiện kiểm tra 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

1

COUNT(*) - Trả về tổng số bản ghi trong một bảng (Bao gồm các bản ghi có giá trị NULL).

COUNT(Column Name) - Trả về tổng số bản ghi Non-NULL. Điều đó có nghĩa là, nó bỏ qua việc đếm các bản ghi có giá trị NULL trong cột cụ thể đó.


0

Tốt nhất là sử dụng

Count(1) in place of column name or * 

để đếm số lượng hàng trong một bảng, nó nhanh hơn bất kỳ định dạng nào vì nó không bao giờ đi để kiểm tra tên cột vào bảng có tồn tại hay không


4
Ít nhất là không đúng với Oracle và đối với các RDBMS khác. Đếm nội bộ (1) được chuyển thành đếm (*). Cụ thể, hiệu suất của số đếm (*) không bị ảnh hưởng bất lợi bởi kích thước của các hàng, đây là một quan niệm sai lầm phổ biến.
David Aldridge

Điều này đúng với SQL Server. Như @Ali Adravi đã nói, COUNT(*)so vớiCOUNT(columnName) sẽ không kiểm tra giá trị cột, vì nó chỉ liệt kê các hàng. Nhưng COUNT(columnName)chậm hơn ngay cả việc countáp dụng trên một idcột! Ít nhất là trong SQL Server, tất nhiên.
ABS

0

Không có sự khác biệt nếu một cột được sửa trong bảng của bạn, nếu bạn muốn sử dụng nhiều hơn một cột hơn bạn phải chỉ định rằng bạn cần bao nhiêu cột để đếm ......

Cảm ơn,


0

Như đã đề cập trong các câu trả lời trước, Count(*) tính cả các NULLcột, trong khi count(Columnname)chỉ tính nếu cột có giá trị.

Luôn luôn là cách tốt nhất để tránh *( Select *,, | count *)


Đó hoàn toàn không phải là cách tốt nhất để tránhCOUNT(*)
David Faber
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.