2017-06-08 2 views
0

Mein SQL ist rostig. Ich habe eine Tabelle, die alle HTTP-Anfragen und ihren Status protokolliert. Was ich will, eine Abfrage tun erstellen, die den Prozentsatz der Ergebnisse zeigen, wo status = pro TagPostgres: Abfrage, die Prozentsatz zurückgibt

hier ‚404 nicht gefunden‘, was die Tabelle

articles=# select * from log limit 1; 

      path    |  ip  | method | status |    time   | id 
-------------------------------+----------------+--------+--------+----------------------------+--------- 
/article/balloon-goons-doomed | 198.51.100.108 | GET | 200 OK |  2016-07-01 06:02:39-05 | 1688046 

ich in der Lage war zu bekommen wie

sieht die rohen zählt wie diese, aber nicht sicher, wie um den Prozentsatz zu bekommen

SELECT date_trunc('day', time) "day", count(*) as count FROM log WHERE 
status='404 NOT FOUND' group by 1 ORDER BY 1; 

Antwort

2

Was brauchen Sie ist conditional aggregation.

Formular PostgreSQL 9.4 gibt es eine explizite Syntax (agg_func(...) FILTER (WHERE <predicate>)) dafür:

SELECT date_trunc('day', time) "day", 
     COUNT(*) FILTER (WHERE status = '404 NOT FOUND')::NUMERIC 
     /COUNT(*) "not found/total" 
FROM  log 
GROUP BY 1 
ORDER BY 1 

Für frühere Versionen, können Sie das mit dem CASE Ausdruck simulieren (Sie müssen nur sicherstellen, dass der CASE Ausdruck der THEN Zweig immer nicht NULL sein; Weglassen des ELSE Zweig NULL s in allen anderen Fällen erzeugen, so COUNT() wird sie nicht gezählt):

SELECT date_trunc('day', time) "day", 
     COUNT(CASE WHEN status = '404 NOT FOUND' THEN status END)::NUMERIC 
     /COUNT(*) "not found/total" 
FROM  log 
GROUP BY 1 
ORDER BY 1 
+0

DANKE das war zunächst 0 zurück, aber mit einer kleinen Änderung SELECT date_trunc ('Tag', Zeit) "Tag", ROUND (COUNT (*) FILTER (WHERE Status = '404 nicht gefunden') :: NUMERIC /COUNT (*) * 100, 2) "404 Prozent" VON log GROUP BY 1 ORDER BY 1 – hypnotoad

+0

@hypnotoad ja, OFC: Ich habe die Umwandlung in 'numeric' vergessen (' int/int' ist 'int' , die für Werte zwischen "0" und "1" immer "0" ist. '100.0 * COUNT (...) FILTER (...)/COUNT (...)' wäre auch eine gültige Lösung, wenn Sie Prozentsätze wünschen. – pozs

0

Ist es in Ordnung, die Gesamtzahl in einer Sub-Abfrage zu wählen?

SELECT date_trunc('day', time) as day, count(*)/totalCount.count * 100 as percentage 
FROM log, 
(
    SELECT count(*) FROM log 
) totalCount 
WHERE status='404 NOT FOUND' group by 1 ORDER BY 1; 
+0

FEHLER: Spalte "totalcount.count" muss in der GROUP BY-Klausel erscheinen oder in einer Aggregatfunktion verwendet werden – hypnotoad

+0

Oh ja, soweit ich weiß, zählt keine Gruppe durch. Ich denke du kannst diese Gruppe komplett um 1 ORDER BY 1 entfernen? –

0

Sie können dies versuchen: Die folgende Beispielabfrage wird die gesamte Anzahl der Datensätze und auch die Anzahl der Aufzeichnungen geben, die Ihre Bedingung zu erfüllen. (Dies ist MYSQL Beispiel)

SELECT 
((COUNT * 100)/TOTAL_REC_COUNT) AS PERCENT 
FROM 
(
SELECT COUNT(*) as TOTAL_REC_COUNT,SUM(CASE WHEN STATUS='404 NOT FOUND' then 1 ELSE 0 END) AS COUNT 
FROM test.sample_table 
) TMP 
Verwandte Themen