Ist es möglich, eine Bedingung in Count () anzugeben?

391

Ist es möglich, eine Bedingung in anzugeben Count()? Ich möchte nur die Zeilen zählen, die beispielsweise "Manager" in der Spalte Position haben.

Ich möchte es in der count-Anweisung tun, nicht mit WHERE . Ich frage darüber, weil ich beide Manager rechnen müssen und andere in der gleichen SELECT(so etwas wie Count(Position = Manager), Count(Position = Other))so WHEREkeinen Sinn , in diesem Beispiel für mich ist.

Agnieszka
quelle
4
Boo an alle * Benutzer, verwenden Sie Count (SomeColumnInYourTable), wobei Position = 'Manager'
Mark Dickinson
6
@Mark: Bei allen modernen Datenbanken macht dies keinen Unterschied.
Philippe Leybaert
5
@ Mark & ​​Philippe: Eigentlich kann es einen großen Unterschied machen. Wenn das Feld nullwertfähig und nicht indiziert ist, muss die Abfrage jeden Datensatz in der Tabelle berühren, sodass die Verwendung von count (*) und count (field) zu unterschiedlichen Ergebnissen und einer unterschiedlichen Leistung führen kann.
Guffa
4
Ich habe jahrelang Ausführungspläne für count (*) vs count (x) analysiert und bisher keinen einzigen gefunden, der einen Leistungsunterschied aufwies. Deshalb würde ich gerne ein Beispiel für eine Abfrage sehen, bei der es einen Unterschied gibt.
Philippe Leybaert
3
@ Matthew: Wir reden nicht darüber SELECT *, aber SELECT COUNT(*)das ist ein ganz anderes Biest.
Philippe Leybaert

Antworten:

663

Wenn Sie die Abfrage selbst nicht einfach mit einer whereKlausel einschränken können, können Sie die Tatsache verwenden, dass das countAggregat nur die Nicht-Null-Werte zählt:

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

Sie können das sumAggregat auch auf ähnliche Weise verwenden:

select sum(case Position when 'Manager' then 1 else 0 end)
from ...
Guffa
quelle
Was ist, wenn mein Feld eine Ganzzahl ist und ich mit Null übereinstimmen möchte? Auf diese Weise funktioniert es nicht. Wählen Sie count (case IntegerField when 'NULL' dann 1 else null end) von
Faizan
2
@Faizan nullist etwas Besonderes. Verwenden Siecase when IntegerField is null then ...
Peet Brits
Wenn Sie mit booleschen Feldern arbeiten, können Sie SUM(CONVERT(int, IsManager))
Folgendes
2
SQL Server impliziert eine else nullfor- caseAnweisung, sodass das count()Beispiel 10 Zeichen kürzer sein kann (wenn Sie das Leerzeichen zählen).
Michael - Wo ist Clay Shirky
212

Angenommen, Sie möchten die zurückgegebenen Zeilen nicht einschränken, weil Sie auch andere Werte aggregieren, können Sie dies folgendermaßen tun:

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

Nehmen wir an, in derselben Spalte, in der Sie die Werte Manager, Supervisor und Teamleiter hatten, können Sie die Anzahl der einzelnen Werte wie folgt ermitteln:

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
quelle
3
@RedFilter Es ist nicht einmal notwendig, das elseTeil anzugeben , nur enddirekt nach dem 1.
Denis Valeev
7
@Denis: Richtig - Ich lasse das elsein oft, da es die Ergebnisse der case-Anweisung besser dokumentiert, insbesondere für neue SQL-Entwickler. Der Kürze halber kann es in diesem Fall entfernt werden.
RedFilter
30

Die Antwort von @Guffa ist ausgezeichnet. Weisen Sie nur darauf hin, dass eine IF-Anweisung möglicherweise sauberer ist

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

Hängt davon ab, was Sie meinen, aber die andere Interpretation der Bedeutung ist, wo Sie Zeilen mit einem bestimmten Wert zählen möchten, aber die nicht einschränken möchten SELECT , dass NUR diese Zeilen ...

Sie würden es SUM()mit einer Klausel in tun , anstatt wie folgt COUNT(): z

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

Sie können das Pivot-Schlüsselwort auch verwenden, wenn Sie SQL 2005 oder höher verwenden

mehr Infos und von Technet

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

Testdatensatz

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

Meinst du genau das:

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

Wenn ja, dann funktioniert das ja!

Dana
quelle
1
Die Bearbeitung zeigt, dass er die Zeilen nicht mit einer WHERE-Klausel einschränken möchte
KinSlayerUY
4

Ich weiß, dass dies wirklich alt ist, aber ich mag den NULLIFTrick für solche Szenarien und habe bisher keine Nachteile gefunden. Schauen Sie sich einfach mein kopierfähiges und einfügbares Beispiel an, das zwar nicht sehr praktisch ist, aber zeigt, wie man es verwendet.

NULLIF Möglicherweise haben Sie einen kleinen negativen Einfluss auf die Leistung, aber ich denke, es sollte immer noch schneller sein als Unterabfragen.

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

Kommentare geschätzt :-)

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

Ich denke, Sie können eine einfache WHERE-Klausel verwenden, um nur die Anzahl einiger Datensätze auszuwählen.

NawaMan
quelle
Warum bekomme ich eine Abwertung? Nachdem ich geantwortet hatte (oder möglicherweise zur gleichen Zeit), antworteten viele Leute auf die ähnliche Sache und erhielten keine Ablehnung. / :(
NawaMan
4
Sie erhalten eine Abwertung, weil die Frage "Bedingung in Anzahl angeben" NICHT "Werte nach Bedingung zählen" lautet. Sie beantworten also die falsche Frage
Radon8472
3
Es ist ein bisschen unfair, die Antwort herunterzustimmen, als die Antwort geschrieben wurde, war es eine korrekte Lösung für die Frage ... er fügte den zusätzlichen Text 4 Minuten nach dieser Antwort hinzu!
Peter
2

Hier ist, was ich getan habe, um einen Datensatz zu erhalten, der sowohl die Summe als auch die Anzahl, die die Kriterien erfüllten, in jedem Versandbehälter enthielt. Damit kann ich die Frage beantworten: "Wie viele Versandbehälter haben mehr als X% Artikel über Größe 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
user3029478
quelle
-4

Auf diese Weise erhalten Sie die Anzahl der Manager

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