ใน SQL ความแตกต่างระหว่าง count (คอลัมน์) และ count (*) คืออะไร


205

ฉันมีคำถามต่อไปนี้:

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

หากฉันแทนที่การโทรทั้งหมดไปที่count(column_name)จะเป็นcount(*)อย่างไร

คำถามนี้ได้รับแรงบันดาลใจจากฉันจะค้นหาค่าที่ซ้ำกันในตารางใน Oracle ได้อย่างไร .


เพื่อชี้แจงคำตอบที่ยอมรับได้ (และอาจเป็นคำถามของฉัน) การแทนที่count(column_name)ด้วยcount(*)จะส่งคืนแถวพิเศษในผลลัพธ์ที่มีค่า a nullและจำนวนของnullค่าในคอลัมน์

คำตอบ:


235

count(*)นับ NULL และcount(column)ไม่

[แก้ไข] เพิ่มรหัสนี้เพื่อให้ผู้คนสามารถเรียกใช้ได้

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


8
แค่อยากรู้อยากเห็น: ถ้าคุณมีแถวที่มีNULL ทั้งหมดจะนับ (*) ยังคงนับหรือจะนับ (คอลัมน์) สำหรับคอลัมน์ทั้งหมด?
Joel Coehoorn

7
มาตรฐานนี้ใช้กับ DBMS หรือไม่
Eclipse

51
เป็นมูลค่าการกล่าวขวัญว่าถ้าคุณมีคอลัมน์ที่ไม่เป็นโมฆะเช่น ID แล้วการนับ (ID) จะปรับปรุงประสิทธิภาพการทำงานมากกว่าการนับ (*) อย่างมีนัยสำคัญ
tsilb

12
@tsilb: คำตอบที่โพสต์โดย @Alan ระบุว่า "count (*) คำนวณโดยดูที่ดัชนีในตารางคำถามแทนที่จะเป็นแถวข้อมูลจริง" ซึ่งหากเป็นจริงจะทำให้ความคิดเห็นของคุณไม่ถูกต้อง ฉันขอขอบคุณที่ @Alan อาจไม่ถูกต้อง แต่ฉันสนใจแหล่งข้อมูลของคุณเพื่อค้นหาว่าสิ่งใดถูกต้อง
โทนี่

12
@tsilb: เครื่องมือเพิ่มประสิทธิภาพการสืบค้นที่ทันสมัยจำนวนมากจะปรับการนับ (*) เพื่อใช้ดัชนีเมื่อเหมาะสม
แชนนอนชดเชย

37

ความแตกต่างเล็กน้อยอีกประการหนึ่งระหว่างการใช้ * และคอลัมน์เฉพาะคือในกรณีคอลัมน์คุณสามารถเพิ่มคำหลัก DISTINCT และ จำกัด จำนวนให้เป็นค่าที่แตกต่างกัน:

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

1
ควรจัดกลุ่มตามคอลัมน์และกลุ่มที่ถูกนับต่างกันหรือไม่? ไม่เช่นนั้นคุณจะไม่ได้อะไรจากการสืบค้นนี้
steevc

ใช่ขอโทษ .. ฉันไม่ได้สังเกตว่าพวกเขาเป็นคอลัมน์เดียวกันในตัวอย่าง ฉันจะอัปเดตโพสต์
Brannon

16

ความแตกต่างที่ลึกซึ้งและลึกซึ้งอาจเป็นไปได้ว่าในการปรับใช้ฐานข้อมูลจำนวน count (*) จะถูกคำนวณโดยดูที่ดัชนีบนตารางในคำถามแทนที่จะเป็นแถวข้อมูลจริง เนื่องจากไม่มีการระบุคอลัมน์ที่เฉพาะเจาะจงจึงไม่จำเป็นต้องกังวลกับแถวจริงและค่าของคอลัมน์เหล่านั้น (เช่นถ้าคุณนับคอลัมน์ที่ต้องการ) การอนุญาตให้ฐานข้อมูลใช้ข้อมูลดัชนีสามารถทำได้เร็วกว่าการนับเป็นแถว "ของจริง"


5
+1 ใช่แน่นอนจริงสำหรับ Oracle และ PostgreSQL ตั้งแต่ 9.2 เป็นต้นไป
David Aldridge

@DavidAldridge คุณสามารถให้บริการตัวชี้ไปยังเอกสาร (โดยเฉพาะอย่างยิ่งสำหรับ postgresql) ซึ่งมีการกล่าวถึงเรื่องนี้ได้หรือไม่? ขอบคุณ
Bhushan

@Bushan นี่ไงคุณไปwiki.postgresql.org/wiki/Index-only_scans
David Aldridge

10

คำอธิบายในเอกสารช่วยอธิบายสิ่งนี้:

COUNT (*) ส่งคืนจำนวนรายการในกลุ่มรวมถึงค่า NULL และรายการซ้ำ

COUNT (นิพจน์) ประเมินค่านิพจน์สำหรับแต่ละแถวในกลุ่มและส่งคืนจำนวนของค่าที่ไม่เป็นศูนย์

ดังนั้น count (*) จึงรวมค่า Null วิธีอื่นไม่ได้


สำหรับ newbs SQL: คุณต้องการอ้างอิงไฟล์ช่วยเหลืออะไร?
บิล Lizard

10

เราสามารถใช้Stack Exchange Data Explorerเพื่อแสดงความแตกต่างได้ด้วยการสืบค้นง่ายๆ ตารางผู้ใช้ในฐานข้อมูลของ Stack Overflow มีคอลัมน์ที่มักจะเว้นว่างไว้เช่น 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แต่เนื่องจากคอลัมน์ที่ช่วยให้


2

โดยทั่วไปCOUNT(*)ฟังก์ชั่นกลับแถวทั้งหมดจากตารางในขณะที่COUNT(COLUMN_NAME)ไม่ได้; นั่นคือไม่รวมค่า null ที่ทุกคนที่นี่ได้ตอบด้วยที่นี่ แต่ส่วนที่น่าสนใจที่สุดคือการทำให้แบบสอบถามและฐานข้อมูลที่ดีที่สุดมันจะดีกว่าที่จะใช้เว้นแต่ทำนับหลายหรือแบบสอบถามที่ซับซ้อนมากกว่าCOUNT(*) COUNT(COLUMN_NAME)มิฉะนั้นจะลดประสิทธิภาพฐานข้อมูลของคุณลงในขณะที่จัดการกับข้อมูลจำนวนมาก


1
  • ประโยค COUNT (*) บ่งชี้ว่า SQL Server ส่งคืนแถวทั้งหมดจากตารางรวมถึง NULLs
  • 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

1

COUNT(*) - ส่งคืนจำนวนระเบียนทั้งหมดในตาราง (รวมถึงระเบียนที่มีค่า NULL)

COUNT(Column Name) - ส่งคืนจำนวนเรคคอร์ด Non-NULL ทั้งหมด หมายความว่าจะไม่สนใจการนับระเบียนที่มีค่าเป็นศูนย์ในคอลัมน์นั้น


0

เป็นการใช้งานที่ดีที่สุด

Count(1) in place of column name or * 

เพื่อนับจำนวนแถวในตารางมันเร็วกว่ารูปแบบใด ๆ เพราะไม่เคยไปตรวจสอบชื่อคอลัมน์ในตารางที่มีอยู่หรือไม่


4
ไม่ถูกต้องสำหรับ Oracle อย่างน้อยและสำหรับ RDBMS อื่นฉันก็สงสัยเช่นกัน การนับภายใน (1) จะถูกแปลงเป็น count (*) โดยเฉพาะอย่างยิ่งประสิทธิภาพของ count (*) ไม่ได้รับผลกระทบจากขนาดของแถวซึ่งเป็นความเข้าใจผิดที่พบบ่อย
David Aldridge

สิ่งนี้เป็นจริงสำหรับ SQL Server ในฐานะที่เป็น @Ali Adravi กล่าวว่าCOUNT(*)ในการเปรียบเทียบกับCOUNT(columnName)จะไม่ไปตรวจสอบค่าคอลัมน์เพราะมันเป็นเพียงการระบุแถว แต่COUNT(columnName)ช้ากว่าแม้countใช้กับidคอลัมน์! อย่างน้อยใน SQL Server แน่นอน
ABS

0

ไม่มีความแตกต่างหากคอลัมน์หนึ่งมีการแก้ไขในตารางของคุณถ้าคุณต้องการใช้มากกว่าหนึ่งคอลัมน์กว่าที่คุณต้องระบุว่าจำนวนคอลัมน์ที่คุณต้องนับ ......

ขอบคุณ


0

ดังที่กล่าวไว้ในคำตอบก่อนหน้านี้Count(*)นับแม้กระทั่งNULLคอลัมน์ในขณะที่count(Columnname)นับเฉพาะเมื่อคอลัมน์นั้นมีค่า

มันเสมอปฏิบัติที่ดีที่สุดที่จะหลีกเลี่ยง*( Select *, count *, ... )


ไม่ใช่วิธีที่ดีที่สุดที่จะหลีกเลี่ยงCOUNT(*)
David Faber
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.