SQL / MySQL SELECT e médios ao longo de certos valores
Pergunta
Eu tenho que trabalhar com uma ferramenta de análise que mede o serviço Web chamadas para um servidor por hora. Estes measurments são inseridos numa base de dados. O que se segue é um fragmento de uma tal medição:
mysql> SELECT * FROM sample s LIMIT 4;
+---------+------+-------+
| service | hour | calls |
+---------+------+-------+
| WS04 | 04 | 24 |
| WS12 | 11 | 89 |
| WSI64 | 03 | 35 |
| WSX52 | 01 | 25 |
+---------+------+-------+
4 rows in set (0.00 sec)
Como o resultado final, eu gostaria de saber a soma de todas as conclusões serviços web por hora do dia. Obviamente, isto pode ser feito facilmente com SUM () e GROUP BY:
mysql> SELECT hour, SUM(calls) FROM sample s GROUP BY hour;
+------+------------+
| hour | SUM(calls) |
+------+------------+
| 00 | 634 |
| 01 | 642 |
| 02 | 633 |
| 03 | 624 |
| 04 | 420 |
| 05 | 479 |
| 06 | 428 |
| 07 | 424 |
| 08 | 473 |
| 09 | 434 |
| 10 | 485 |
| 11 | 567 |
| 12 | 526 |
| 13 | 513 |
| 14 | 555 |
| 15 | 679 |
| 16 | 624 |
| 17 | 796 |
| 18 | 752 |
| 19 | 843 |
| 20 | 827 |
| 21 | 774 |
| 22 | 647 |
| 23 | 533 |
+------+------------+
12 rows in set (0.00 sec)
Meu problema é que em conjuntos antigos, as chamadas de serviço web nas horas de [00-11] já foram resumidos. A simples declaração como listado acima, portanto, levar a
mysql> SELECT hour, SUM(calls) FROM sample s GROUP BY hour;
+------+------------+
| hour | SUM(calls) |
+------+------------+
| 00 | 6243 | <------ sum of hours 00-11!
| 12 | 526 |
| 13 | 513 |
| 14 | 555 |
| 15 | 679 |
| 16 | 624 |
| 17 | 796 |
| 18 | 752 |
| 19 | 843 |
| 20 | 827 |
| 21 | 774 |
| 22 | 647 |
| 23 | 533 |
+------+------------+
13 rows in set (0.00 sec)
Este é um resultado indesejável. Para fazer com que os antigos conjuntos [00,12, ..., 23] comparável aos novos conjuntos [00,01, ..., 23] Eu gostaria de ter uma declaração de que calcula a média do valor de [00] e distribui-lo sobre as horas que faltam, por exemplo:
+------+------------+
| hour | SUM(calls) |
+------+------------+
| 00 | 6243/11 |
| 01 | 6243/11 |
[...]
| 12 | 526 |
[...]
| 23 | 533 |
+------+------------+
Eu posso facilmente fazer isso usando tabelas temporárias ou pontos de vista, mas eu não sei como fazer isso sem eles.
Todas as idéias? Porque isso está me deixando louco: P
Solução
Você vai precisar de um conjunto de linhas com 12 linhas em-lo para fazer uma junção.
A solução mais simples será combinando 12 declarações SELECT
em uma união:
SELECT COALESCE(morning.hour, sample.hour),
SUM(CASE WHEN morning.hour IS NULL THEN calls ELSE calls / 12 END) AS calls
FROM sample
LEFT JOIN
(
SELECT 0 AS hour
UNION ALL
SELECT 1
...
UNION ALL
SELECT 11
) AS morning
ON sample.hour = 0 AND sample.service IN ('old_service1', 'old_service2')
GROUP BY
1
Outras dicas
Você está provavelmente melhor fazer isso com tabelas temporárias / views (eu recomendo uma vista sobre uma tabela temporária) ou você vai acabar com uma declaração específica caso desagradável que será um pesadelo para gerir ao longo do tempo.