Eu tenho a seguinte consulta para coletar dados para um relatório:
SELECT COUNT(*) as inspected,
count(*) filter(where status="fail") as failed,
count(*) filter(where status="deficient") as impaired,
count(*) filter(where status="pass") as passed,
device_types.name
FROM inspection_data
INNER JOIN devices ON devices.id=inspection_data.device_id
INNER JOIN device_types ON devices.device_type_id=device_types.id
WHERE inspection_id = 3
GROUP BY device_types.id
ORDER BY device_types.name
Esta consulta está funcionando conforme o esperado (embora eu estejacerteza poderia ser otimizado um pouco. O SQL não é o meu ponto forte). O problema é que agora quero reunir mais um dado de resumo. Quero contar o número de cada device_type_id na tabela de dispositivos para esse location_id.
Vou tentar mapear as tabelas do banco de dados:
| devices | device_types | inspection_data |
|:--------------:|:------------:|:---------------:|
| id | id | id |
| device_type_id | name | inspection_id |
| location_id | | device_id |
| | | status |
Então, quando executo a consulta, estou recebendo resultados semelhantes a este:
| inspected | failed | impaired | passed | name |
|:---------:|:------:|:--------:|--------|----------------------------|
| 6 | 0 | 2 | 4 | Air Sampling Type Detector |
| 9 | 1 | 1 | 7 | Alarm Bell |
E isso é ótimo. Meu problema é que nem todos os dispositivos de um local precisam ser inspecionados durante uma inspeção. Por exemplo, digamos que existem 15 dispositivos "Alarm Bell" para este local, mas apenas 9 foram inspecionados como parte dessa inspeção, conforme a tabela acima. Como incluo outra coluna nesta saída, nomeado "total" com um valor de 15 para o tipo de dispositivo Campainha de alarme e assim por diante para cada um dos tipos de dispositivo no relatório?
Espero ter descrito adequadamente o que estou tentandofaçam. Estou totalmente perplexo em como fazer isso sem executar uma segunda consulta, e realmente não quero fazer isso, a menos que seja absolutamente necessário, porque apenas atrapalha ainda mais o código.
Respostas:
0 para resposta № 1Eu acho que você quer um left join
. No entanto, não tenho certeza de qual tabela vai primeiro. Meu melhor palpite é:
SELECT COUNT(*) as total,
COUNT(id.device_id) as inspected,
COUNT(id.device_id) filter (where status="fail") as failed,
COUNT(id.device_id) filter (where status="deficient") as impaired,
COUNT(id.device_id) filter (where status="pass") as passed,
dt.name
FROM devices d INNER JOIN
device_types dt
ON d.device_type_id = dt.id LEFT JOIN
inspection_data id
ON d.id = id.device_id AND
id.inspection_id = 3
GROUP BY dt.id
ORDER BY dt.name