postgresql - sql - Anzahl der "wahren" Werte

97
myCol
------
 true
 true
 true
 false
 false
 null

Wenn ich in der obigen Tabelle Folgendes tue:

select count(*), count(myCol);

Ich bekomme 6, 5

Ich bekomme, 5da es den Null-Eintrag nicht zählt.

Wie zähle ich auch die Anzahl der wahren Werte (3 im Beispiel)?

(Dies ist eine Vereinfachung und ich verwende tatsächlich einen viel komplizierteren Ausdruck innerhalb der Zählfunktion.)

Zusammenfassung bearbeiten: Ich möchte auch eine einfache Anzahl (*) in die Abfrage aufnehmen, kann daher keine where-Klausel verwenden

EoghanM
quelle
Steht 't' für True und 'f' für False? Oder suchen Sie etwas wie SELECT COUNT (DISTINCT myCol)?
Shamit Verma
Schauen Sie sich mein zweites Beispiel an, Sie können dort ein werfen, WHERE myCol = truewenn Sie möchten, und wenn Sie das erste entfernen *,, wird nur die Nummer zurückgegeben.
Vol7ron
@Shamit ja t steht für wahr und f steht für falsch, ich habe die Frage aktualisiert
EoghanM
Sie können Ihre Frage / Abfrage genauso gut nicht vereinfachen ... Ihre Anforderungen schränken die besseren Leistungsmöglichkeiten ein und die Leute antworten mit ineffizienten Antworten, die ohne guten Grund auftauchen.
Vol7ron
1
@ vol7ron zu meiner Verteidigung muss es einige Vereinfachungen geben, um eine verständliche Frage zu stellen, aber ja, ich habe es zu stark vereinfacht, als ich ursprünglich gepostet habe.
EoghanM

Antworten:

131
SELECT COALESCE(sum(CASE WHEN myCol THEN 1 ELSE 0 END),0) FROM <table name>

oder, wie Sie selbst herausgefunden haben:

SELECT count(CASE WHEN myCol THEN 1 END) FROM <table name>
Daniel
quelle
Dies ist ein guter Hack und bekommt die richtige Antwort von mir. Ich werde es akzeptieren, wenn nicht jemand eine kürzere Lösung findet?
EoghanM
2
auch, warum hast du summiert (.. DANN 1 SONST 0) anstatt gezählt (.. DANN wahr sonst null)?
EoghanM
5
Nein ... ich war mir nur nicht sicher, welche Werte zählen würden () ... und ich wusste, dass diese Summe den Trick machte. Aber Vorsicht: Beim zweiten Gedanken glaube ich, dass sum () über nur null Werte null zurückgibt, also sollte es COALESCE (sum (...), 0) für Sie sein, oder mit anderen Worten, count () ist besser,
Daniel
1
@EoghanM, siehe kürzere Antwort mit Besetzung.
Dwayne Towell
1
Sie können tatsächlich weglassen ELSE null, um das gleiche Ergebnis zu erhalten.
200_erfolg
90

Wandle den Booleschen Wert in eine ganze Zahl und eine Summe um.

SELECT count(*),sum(myCol::int);

Du verstehst 6,3.

Dwayne Towell
quelle
3
Plus1: Netter Hack! Dies ist wahrscheinlich sogar schneller als meine Lösung.
Daniel
1
Dies ist die beste und kürzeste Lösung (und hat Entsprechungen in vielen anderen Programmierumgebungen und Software). Sollte mehr
3
Die Besetzung von int and count ist eindeutig die prägnanteste, aber das macht es nicht am besten. Ich würde dies nicht unterstützen, da viele Umgebungen die 0/1-Darstellung für false / true verwenden, viele jedoch 0 / ungleich Null, einschließlich -1. Ich bin damit einverstanden, dass es ein "Hack" ist, und Casts sind heikel genug, wenn sie keine "Hacks" sind. Ich werde nicht ablehnen, aber ich würde es nicht unterstützen.
Andrew Wolfe
79

Seit PostgreSQL 9.4 gibt es die FILTERKlausel , die eine sehr präzise Abfrage ermöglicht, um die wahren Werte zu zählen:

select count(*) filter (where myCol)
from tbl;

Die obige Abfrage ist insofern ein schlechtes Beispiel, als eine einfache WHERE-Klausel ausreichen würde und nur zur Demonstration der Syntax dient. Die FILTER-Klausel zeigt, dass es einfach ist, sie mit anderen Aggregaten zu kombinieren:

select count(*), -- all
       count(myCol), -- non null
       count(*) filter (where myCol) -- true
from tbl;

Die Klausel ist besonders praktisch für Aggregate in einer Spalte, die eine andere Spalte als Prädikat verwendet, und ermöglicht gleichzeitig das Abrufen unterschiedlich gefilterter Aggregate in einer einzelnen Abfrage:

select count(*),
       sum(otherCol) filter (where myCol)
from tbl;
Ilja Everilä
quelle
2
Dies ist die beste Antwort für PG> 9.4 und ist unglaublich schnell
Juan Ricardo
47

Wahrscheinlich ist der beste Ansatz die Verwendung der Nullif-Funktion.

allgemein

select
    count(nullif(myCol = false, true)),  -- count true values
    count(nullif(myCol = true, true)),   -- count false values
    count(myCol);

oder kurz gesagt

select
    count(nullif(myCol, true)),  -- count false values
    count(nullif(myCol, false)), -- count true values
    count(myCol);

http://www.postgresql.org/docs/9.0/static/functions-conditional.html

Wrobell
quelle
2
Ihr "im Allgemeinen" sieht falsch aus: AFAICS nullif([boolean expression], true)gibt zurück, falsewenn [boolescher Ausdruck] falsch ist, und nullwenn es wahr ist, werden Sie die falschen Werte zählen. Ich denke du willst nullif([boolean expression], false).
rjmunro
Ja, der "allgemeine" Fall sollte umgekehrt sein. Fest. Vielen Dank.
Wrobell
1
Yuk. Dieses Update ist wirklich verwirrend. AFAICS zählt jetzt wahre oder null Werte. Ich denke, dass nullif([boolean expression], false)es viel einfacher ist, es so umzuformulieren, dass Sie es immer haben . Sie können dann den booleschen Ausdrucksteil so variieren, wie Sie möchten, in diesem Fall myCol = trueum wahre Werte oder myCol = falsefalsche Werte zu zählen, odername='john' zu zählen um Leute mit dem Namen John usw. zu zählen
rjmunro
19

Die kürzeste und faulste Lösung (ohne Gießen) wäre die Verwendung der folgenden Formel:

SELECT COUNT(myCol OR NULL) FROM myTable;

Versuch es selber:

SELECT COUNT(x < 7 OR NULL)
   FROM GENERATE_SERIES(0,10) t(x);

gibt das gleiche Ergebnis als

SELECT SUM(CASE WHEN x < 7 THEN 1 ELSE 0 END)
   FROM GENERATE_SERIES(0,10) t(x);
Le Droid
quelle
Dies ist definitiv eine schönere Lösung als meine :)
Daniel
Sehr aufschlussreiche Antwort.
Lucasarruda
7

In MySQL können Sie dies auch tun:

SELECT count(*) AS total
     , sum(myCol) AS countTrue --yes, you can add TRUEs as TRUE=1 and FALSE=0 !!
FROM yourTable
;

Ich denke, dass dies in Postgres funktioniert:

SELECT count(*) AS total
     , sum(myCol::int) AS countTrue --convert Boolean to Integer
FROM yourTable
;

oder besser (um :: zu vermeiden und die Standard-SQL-Syntax zu verwenden):

SELECT count(*) AS total
     , sum(CAST(myCol AS int)) AS countTrue --convert Boolean to Integer
FROM yourTable
;
ypercubeᵀᴹ
quelle
Dies ist die einfachste Lösung, die ich je gesehen habe ^ _ ^
JiaHao Xu
7
select f1,
       CASE WHEN f1 = 't' THEN COUNT(*) 
            WHEN f1 = 'f' THEN COUNT(*) 
            END AS counts,
       (SELECT COUNT(*) FROM mytable) AS total_counts
from mytable
group by f1

Oder vielleicht das hier

SELECT SUM(CASE WHEN f1 = 't' THEN 1 END) AS t,
       SUM(CASE WHEN f1 = 'f' THEN 1 END) AS f,
       SUM(CASE WHEN f1 NOT IN ('t','f') OR f1 IS NULL THEN 1 END) AS others,
       SUM(CASE WHEN f1 IS NOT NULL OR f1 IS NULL THEN 1 ELSE 0 END) AS total_count
FROM mytable;
Kuberchaun
quelle
+1 Wenn myColAusdruck ein Boolescher where (myCol)
Wert
Entschuldigung, ich habe mein Beispiel stark vereinfacht: Ich kann keine where-Klausel verwenden, da ich auch eine Gesamtzahl zurückgeben möchte, die die Gesamtzahl der Zeilen sowie eine Anzahl der wahren Werte darstellt.
EoghanM
7

Konvertieren Sie einfach das boolesche Feld in eine Ganzzahl und machen Sie eine Summe. Dies funktioniert auf postgresql:

select sum(myCol::int) from <table name>

Hoffentlich hilft das!

Jaspreet Singh
quelle
Es ist weder schneller noch präziser als die anderen Lösungen. Ich glaube, Sie kommen von Oracle, wenn die Verwendung von Ints als Boolescher Wert für Sie intuitiver ist.
Daniel
4
SELECT count(*)         -- or count(myCol)
FROM   <table name>     -- replace <table name> with your table
WHERE  myCol = true;

Hier ist ein Weg mit der Fensterfunktion:

SELECT DISTINCT *, count(*) over(partition by myCol)
FROM   <table name>;

-- Outputs:
-- --------------
-- myCol | count
-- ------+-------
--  f    |  2
--  t    |  3
--       |  1
vol7ron
quelle
Leider kann ich für das kompliziertere Beispiel, auf das ich diese Lösung anwende, nicht mehrere Zeilen zurückgeben.
EoghanM
Ja, aber Sie können es weiter einschränken, indem Sie es einfach hinzufügen WHERE myCol = true. Ich habe das zweite Beispiel nicht bereitgestellt, weil es schneller ist, sondern eher als Lehrmaterial für die Fensterfunktionen von Postgres, mit denen viele Benutzer nicht vertraut sind oder die sie nicht kennen.
Vol7ron
0
select count(myCol)
from mytable
group by myCol
;

gruppiert die 3 möglichen Zustände von bool (false, true, 0) in drei Zeilen, was besonders praktisch ist, wenn Sie zusammen mit einer anderen Spalte wie day gruppieren

Hazard5000
quelle