Quero juntar duas tabelas e obter o resultado mais recente de cada uma dessas duas em uma única tabela. Estou meio preocupado com a velocidade também, já que as mesas estão crescendo meio rápido. Perto de 60-70k registros por dia. Mais tarde, irei para o particionamento, mas isso é outro problema. Agora eu tenho uma tabela principal com as devices
informações.
+--------+-----------+---------+
| id | Name | type |
+--------+-----------+---------+
| 1 | Oh | A |
| 2 | This | A |
| 3 | Is | B |
| 4 | Hard | A |
+--------+-----------+---------+
De acordo com o tipo, eles têm alguns dados em tabelas diferentes. O tipo A é
+--------+-----------+------------------+---------+---------+
| id | device_id | stats_time | status | noise |
+--------+-----------+------------------+---------+---------+
| 1 | 1 | 2012-10-23 07:50 | foo | 10 |
| 2 | 1 | 2012-10-23 16:59 | bar | 12 |
| 3 | 2 | 2012-10-23 15:11 | bar | 0 |
| 4 | 4 | 2012-10-23 23:23 | foo | 25 |
+--------+-----------+------------------+---------+---------+
Tipo B é
+--------+-----------+------------------+---------+---------+
| id | device_id | stats_time | status | signal |
+--------+-----------+------------------+---------+---------+
| 1 | 3 | 2012-10-23 04:50 | foo | 1000 |
| 2 | 3 | 2012-10-23 05:59 | bar | 450 |
| 3 | 3 | 2012-10-23 09:11 | bar | 980 |
| 4 | 3 | 2012-10-23 10:23 | foo | 0 |
+--------+-----------+------------------+---------+---------+
Estou quebrando a cabeça por uma consulta para acabar com algo assim
+--------+-----------+------------------+---------+---------+---------+
| id | device_id | stats_time | status | signal | noise |
+--------+-----------+------------------+---------+---------+---------+
| 1 | 1 | 2012-10-23 16:59 | bar | 12 | |
| 2 | 2 | 2012-10-23 15:11 | bar | 0 | |
| 3 | 3 | 2012-10-23 10:23 | foo | | 0 |
| 4 | 4 | 2012-10-23 23:23 | foo | 25 | |
+--------+-----------+------------------+---------+---------+---------+
Usar a consulta abaixo não é bom, pois recebo duas colunas destats_time
SELECT devices.id AS id, A.stats_time , B.stats_time
FROM devices
LEFT JOIN A ON devices.id = A.device_id
LEFT JOIN B ON devices.id = B.device_id
GROUP BY devices.id
Antes de acabar usando tabelas diferentes para os tipos de dispositivo, usei para obter os resultados com o seguinte, mas acabei ficando muito lento
SELECT *
FROM (
SELECT *
FROM A
ORDER BY stats_time DESC, id ASC
) AS d
RIGHT JOIN devices ON A.device_id = devices.id
GROUP BY devices.id
Afirmei nos comentários acima que este parece ser um caso de relacionamento supertipo-subtipo, mas, como alterar a estrutura do banco de dados pode ser uma decisão que está fora do escopo desta questão, vou me concentrar em oferecer uma solução para sua situação atual.
Então, depois de algumas edições, decidi incluir algumas
DDL
declarações e uma breve descrição de minhas suposições sobre a estrutura do seu banco de dados, esperando que, dessa forma, minha resposta e suas consultas envolvidas sejam mais facilmente compreendidas.Compreensão da situação e hipotética
DDL
Conforme eu percebo o cenário,
type_a
etype_b
podem ser dois tipos diferentes dereading
oumeasurement
que você está coletando para cada umdevice.
Dessa forma, embora eu não tenha certeza do significado das colunas
type_a.type_a_id
etype_b.type_b_id
, presumo que sejam algum tipo de ousequential_number
em cada tabela respectiva. Da mesma forma, as colunas e são os pontos exatos no tempo em que a publica algum tipo de arquivo .row_number
record_identifier
type_a.stats_time
type_b.stats_time
device
reading
Também assumi que
type_a.device_id
sãotype_b.device_id
FOREIGN KEYS que fazem referência àdevice
tabela que, por sua vez, tem a colunadevice.device_id
sendo usada como uma espécie desequential_number
ourow_number
ourecord_identifier
que você definiu como PRIMARY KEY.Tendo descrito minha compreensão do estado de coisas, observe que não estou sugerindo que esta seja a estrutura ideal (já que, naturalmente, não estou familiarizado com o cenário real, pode faltar normalização, integridade etc.), estou apenas fazendo algumas suposições com base nas amostras de dados e consultas que você apresentou, a fim de fornecer uma possível solução para sua situação específica. Então vamos as especulações
DDL
:proposta inicial
E então, aqui está minha primeira consulta enviada que, mantendo a ideia original, foi reformatada e adaptada à
DDL
estrutura que foi adicionada posteriormente:Como você pode ver, estou usando a função COALESCE() que somente se a coluna
type_a.stats_time
contiver umNULL
valor, então 'imprime' o valor da colunatype_b.stats_time
e funciona de maneira semelhante para as colunastype_a.status
e .type_b.status
Proposta subsequente
Primeiro método
Agora, depois de reler sua pergunta e depois de algumas interações de comentários, entendo que o que você realmente deseja é obter um único conjunto de resultados contendo apenas duas linhas - uma linha incluindo colunas correspondentes ao
type_a.stats_time
valor mais recente e uma linha contendo colunas relacionadas aotype_b.stats_time
valor mais recente —. Portanto sugiro a seguinte consulta que também recupera dados daDDL
proposta acima:Observe o uso do operador UNION , que serve para combinar em um único conjunto de resultados a última linha de
type_a
(com base nostats_time
valor da coluna mais recente, obtido por meio da função MAX() em uma subconsulta na cláusula WHERE) com o último row intype_b
(da mesma forma, com base nostats_time
valor da coluna mais recente, também obtido por meio da função MAX() em uma subconsulta na cláusula WHERE).Segundo método
Você também pode tentar com esta consulta alternativa, que classifica cada um dos conjuntos de resultados combinados com base na
stats_time
coluna em cada instrução SELECT respectiva usando as cláusulas ORDER BY e LIMIT .Depois de comparar o desempenho de todos os métodos sugeridos, será fácil definir qual é o melhor para suas necessidades. Além disso, se um deles resolver o seu problema, você poderá configurá-lo como um
VIEW
, assim a recuperação futura de dados será mais fácil de obter.Sobre o aspecto de desempenho de velocidade de suas consultas, você pode começar a refinar tais questões prestando atenção especial à definição de índices nas colunas apropriadas, por exemplo,
type_a.stats_time
etype_b.stats_time
.Eu vejo isso como 2 etapas:
JOIN
ouUNION
as duas tabelas.O passo 1 é uma variante de groupwise max :
Isso pode ser benéfico para o desempenho:
Idem para
TableB
esignal
. Execute-os manualmente para ver se os acertei.Seu exemplo não mostra um caso em que ambos
signal
enoise
existem para o mesmodevice_id
. Vou assumir que é realmente o caso, portantoUNION
:Passo 2: