Apakah mungkin menentukan kondisi dalam Count ()?

392

Apakah mungkin untuk menentukan kondisi dalam Count()? Saya ingin menghitung hanya baris yang memiliki, misalnya, "Manajer" di kolom Posisi.

Saya ingin melakukannya dalam pernyataan hitungan, tidak menggunakan WHERE; Aku bertanya tentang hal itu karena saya perlu untuk menghitung Manajer dan lain di sama SELECT(seperti Count(Position = Manager), Count(Position = Other))jadi WHEREada gunanya bagi saya dalam contoh ini.

agnieszka
sumber
4
Boo ke semua * pengguna, gunakan Count (SomeColumnInYourTable) di mana Position = 'Manager'
Mark Dickinson
6
@ Mark: Pada semua database modern, ini tidak ada bedanya.
Philippe Leybaert
5
@ Mark & ​​Philippe: Sebenarnya itu bisa membuat perbedaan besar. Jika bidang dapat dibatalkan dan tidak diindeks, kueri harus menyentuh setiap catatan dalam tabel, jadi menggunakan hitungan (*) dan jumlah (bidang) dapat memberikan hasil yang berbeda dan kinerja yang berbeda.
Guffa
4
Saya telah menganalisis rencana eksekusi untuk hitungan (*) vs hitungan (x) selama bertahun-tahun, dan sejauh ini saya belum menemukan satu pun yang menunjukkan perbedaan dalam kinerja. Itu sebabnya saya benar-benar ingin melihat contoh kueri di mana ada perbedaan.
Philippe Leybaert
3
@ Matthew: kita tidak berbicara tentang SELECT *, tetapi SELECT COUNT(*), yang merupakan binatang yang sama sekali berbeda.
Philippe Leybaert

Jawaban:

664

Jika Anda tidak bisa membatasi kueri itu sendiri dengan whereklausa, Anda bisa menggunakan fakta bahwa countagregat hanya menghitung nilai-nilai non-nol:

select count(case Position when 'Manager' then 1 else null end)
from ...

Anda juga dapat menggunakan sumagregat dengan cara yang sama:

select sum(case Position when 'Manager' then 1 else 0 end)
from ...
Guffa
sumber
bagaimana jika bidang saya bilangan bulat dan saya ingin mencocokkan nol. itu tidak bekerja dengan cara ini pilih hitungan (case IntegerField ketika 'NULL' lalu 1 else null end) dari
Faizan
2
@ Saizan nullspesial. Gunakancase when IntegerField is null then ...
Peet Brits
Saat bekerja dengan bidang boolean Anda dapat menggunakan ini:SUM(CONVERT(int, IsManager))
Simon_Weaver
2
SQL Server mengimplikasikan pernyataan else nullfor case, jadi count()contohnya bisa 10 karakter lebih pendek (jika Anda menghitung spasi).
Michael - Di mana Clay Shirky
213

Dengan asumsi Anda tidak ingin membatasi baris yang dikembalikan karena Anda mengumpulkan nilai-nilai lain juga, Anda bisa melakukannya seperti ini:

select count(case when Position = 'Manager' then 1 else null end) as ManagerCount
from ...

Katakanlah dalam kolom yang sama Anda memiliki nilai Manajer, Pengawas, dan Pemimpin Tim, Anda bisa mendapatkan hitungan masing-masing seperti ini:

select count(case when Position = 'Manager' then 1 else null end) as ManagerCount,
    count(case when Position = 'Supervisor' then 1 else null end) as SupervisorCount,
    count(case when Position = 'Team Lead' then 1 else null end) as TeamLeadCount,
from ...
RedFilter
sumber
3
@RedFilter Bahkan tidak perlu untuk menentukan elsebagian, hanya endsetelah 1.
Denis Valeev
7
@Denis: benar - Saya sering keluar elsekarena lebih baik mendokumentasikan hasil dari pernyataan kasus, terutama untuk pengembang SQL novie. Untuk singkatnya, dapat dihapus dalam kasus ini.
RedFilter
30

@Guffa jawaban sangat bagus, hanya tunjukkan bahwa mungkin lebih bersih dengan pernyataan IF

select count(IF(Position = 'Manager', 1, NULL)) as ManagerCount
from ...
Hivenfour
sumber
21

Tergantung apa yang Anda maksud, tetapi interpretasi lain dari artinya adalah di mana Anda ingin menghitung baris dengan nilai tertentu, tetapi tidak ingin membatasi SELECTuntuk HANYA baris itu ...

Anda akan melakukannya menggunakan SUM()klausa, seperti ini alih-alih menggunakan COUNT(): mis

SELECT SUM(CASE WHEN Position = 'Manager' THEN 1 ELSE 0 END) AS ManagerCount,
    SUM(CASE WHEN Position = 'CEO' THEN 1 ELSE 0 END) AS CEOCount
FROM SomeTable
AdaTheDev
sumber
13

Anda juga dapat menggunakan Kata Kunci Pivot jika Anda menggunakan SQL 2005 atau lebih tinggi

info lebih lanjut dan dari Technet

SELECT *
FROM @Users
PIVOT (
    COUNT(Position)
    FOR Position
    IN (Manager, CEO, Employee)
) as p

Kumpulan Data Uji

DECLARE @Users TABLE (Position VARCHAR(10))
INSERT INTO @Users (Position) VALUES('Manager')
INSERT INTO @Users (Position) VALUES('Manager')
INSERT INTO @Users (Position) VALUES('Manager')
INSERT INTO @Users (Position) VALUES('CEO')
INSERT INTO @Users (Position) VALUES('Employee')
INSERT INTO @Users (Position) VALUES('Employee')
INSERT INTO @Users (Position) VALUES('Employee')
INSERT INTO @Users (Position) VALUES('Employee')
INSERT INTO @Users (Position) VALUES('Employee')
INSERT INTO @Users (Position) VALUES('Employee')
Matthew Whited
sumber
5

Apakah maksud Anda hanya ini:

SELECT Count(*) FROM YourTable WHERE Position = 'Manager'

Jika demikian, maka ya berhasil!

Dana
sumber
1
Hasil edit menunjukkan bahwa ia tidak ingin membatasi baris dengan klausa WHERE
KinSlayerUY
4

Saya tahu ini benar-benar tua, tapi saya suka NULLIFtrik untuk skenario seperti itu, dan sejauh ini saya tidak menemukan kelemahan. Lihat saja contoh copy & paste saya, yang sebenarnya tidak terlalu praktis, tetapi menunjukkan cara menggunakannya.

NULLIF mungkin memberi Anda dampak negatif kecil pada kinerja, tapi saya kira itu masih harus lebih cepat daripada subqueries.

DECLARE @tbl TABLE ( id [int] NOT NULL, field [varchar](50) NOT NULL)

INSERT INTO @tbl (id, field)
SELECT 1, 'Manager'
UNION SELECT 2, 'Manager'
UNION SELECT 3, 'Customer'
UNION SELECT 4, 'Boss'
UNION SELECT 5, 'Intern'
UNION SELECT 6, 'Customer'
UNION SELECT 7, 'Customer'
UNION SELECT 8, 'Wife'
UNION SELECT 9, 'Son'

SELECT * FROM @tbl

SELECT 
    COUNT(1) AS [total]
    ,COUNT(1) - COUNT(NULLIF([field], 'Manager')) AS [Managers]
    ,COUNT(NULLIF([field], 'Manager')) AS [NotManagers]
    ,(COUNT(1) - COUNT(NULLIF([field], 'Wife'))) + (COUNT(1) - COUNT(NULLIF([field], 'Son'))) AS [Family]
FROM @tbl

Komentar dihargai :-)

z00l
sumber
2
SELECT COUNT(*) FROM bla WHERE Position = 'Manager'
Peter
sumber
2

Saya pikir Anda dapat menggunakan klausa WHERE sederhana untuk memilih hanya menghitung beberapa catatan.

NawaMan
sumber
Mengapa saya mendapat suara turun? Setelah saya menjawab (atau mungkin bersamaan), banyak orang menjawab hal serupa dan mereka tidak mendapatkan downvote. / :(
NawaMan
4
Anda mendapatkan downvote karena pertanyaannya adalah "tentukan kondisi dalam Hitungan" BUKAN "Hitung nilai berdasarkan kondisi". Jadi, Anda menjawab pertanyaan yang salah
Radon8472
3
Agak tidak adil untuk merendahkan jawaban, ketika jawabannya ditulis itu adalah solusi yang tepat untuk pertanyaan itu .... ia menambahkan teks tambahan 4 menit setelah jawaban ini!
Peter
2

Berikut adalah apa yang saya lakukan untuk mendapatkan kumpulan data yang mencakup total dan jumlah yang memenuhi kriteria, dalam setiap kontainer pengiriman. Biarkan saya menjawab pertanyaan "Berapa banyak kontainer pengiriman yang memiliki lebih dari X% item di atas ukuran 51"

select
   Schedule,
   PackageNum,
   COUNT (UniqueID) as Total,
   SUM (
   case
      when
         Size > 51 
      then
         1 
      else
         0 
   end
) as NumOverSize 
from
   Inventory 
where
   customer like '%PEPSI%' 
group by
   Schedule, PackageNum
pengguna3029478
sumber
-4

Dengan ini Anda akan mendapatkan hitungan untuk manajer

Select Position, count(*) as 'Position Counter'
from your_table 
group by Position 
Rafael
sumber