Miglior query per ottenere il rapporto successo / fallimento dalla tabella dei fatti del magazzino
-
15-11-2019 - |
Domanda
Sto cercando di sintonizzare una query e vorrei un feedback. Ho un tavolo da magazzino job_fact
con un'unità di misura per l'evento finale del lavoro (final_event_type
). Sto cercando di eseguire una query sul fatto che mi darà un rapporto successo / fallimento. Ecco cosa ho finora:
SELECT
CASE WHEN jf.final_event_type IN (4,6,8,9) THEN count(final_event_type) END as num_failures,
CASE WHEN jf.final_event_type IN (5,7,10) THEN count(final_event_type) END as num_successes
FROM job_fact jf
GROUP BY jf.final_event_type;
.
Questa query mi dà solo i veri valori di successo e guasto in un risultato a due fili:
+----------------------+-----------------------+
| num_failures | num_successes |
+----------------------+-----------------------+
| [NULL] | 6 |
| 14 | [NULL] |
+----------------------+-----------------------+
.
Qualcuno sa se c'è un modo per a) ottenere i risultati su una riga, e b) essere in grado di calcolare il rapporto tra i due (ad esempio la percentuale di guasto). Suppongo che qualcuno mi dimarmi che sto meglio a scrivere una procedura per questo, ma mi piacerebbe evitarlo se possibile. So che c'è un modo elegante per farlo, ma il mio sql-foo è carente oggi credo.
Sto eseguendo postgresql 9.0.1. Grazie per qualsiasi assistenza che puoi offrire.
Aggiornamento
Basato sulla risposta scelta (da @ronnis), ecco la mia query finale, nel caso ti stessi chiedendo:
.select
sum(case when final_event_type in(4,6,8,9) then 1 else 0 end) as failures,
sum(case when final_event_type in(5,7,10) then 1 else 0 end) as successes,
count(final_event_type) as total_events,
sum(case when final_event_type in(4,6,8,9) then 1 else 0 end) / count(final_event_type)::decimal as failure_percentage,
sum(case when final_event_type in(5,7,10) then 1 else 0 end) / count(final_event_type)::decimal as success_percentage
from job_fact;
Soluzione
If where final_event_type in(4,5,6,7,8,9,10)
would hit most of the table, I think the following would be pretty performant:
select sum(case when final_event_type in(4,6,8,9) then 1 else 0 end) as failures
,sum(case when final_event_type in(5,7,10) then 1 else 0 end) as successes
from job_fact;
Edit
I don't know how postgresq executes the above query. In Oracle, there is an access path called Index Fast Full scan, which basically treats the index as a table. No traversal (slow), just a full scan (efficient). The benefit is that an index on {final_event_type}
could be significantly smaller to scan than the whole table.
(I'm not mentioning bitmap indexes, because that would be faster still).
Altri suggerimenti
SELECT num_failures, num_successesc, (num_failures/Total), (num_successesc/Total)
FROM (
SELECT
(SELECT COUNT(*) FROM job_fact WHERE final_event_type IN (4,6,8,9)) AS "num_failures"
(SELECT COUNT(*) FROM job_fact WHERE final_event_type IN (5,7,10)) AS "num_successesc"
(SELECT COUNT(*) FROM job_fact WHERE final_event_type IN (4,6,8,9,5,7,10)) AS "Total"
) PQ