我想加入两个表并在一个表中从这两个表中的每一个中获取最新结果。我也有点担心速度,因为表格增长得有点快。每天接近 60-70k 条记录。稍后我将进行分区,但这是另一个问题。现在我有一个包含devices
信息的主表。
+--------+-----------+---------+
| id | Name | type |
+--------+-----------+---------+
| 1 | Oh | A |
| 2 | This | A |
| 3 | Is | B |
| 4 | Hard | A |
+--------+-----------+---------+
根据类型,他们在不同的表中有一些数据类型 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 |
+--------+-----------+------------------+---------+---------+
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 |
+--------+-----------+------------------+---------+---------+
我一直在努力寻找一个查询,最终得到这样的结果
+--------+-----------+------------------+---------+---------+---------+
| 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 | |
+--------+-----------+------------------+---------+---------+---------+
使用下面的查询不好,因为我得到两列stats_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
在我最终为设备类型使用不同的表之前,我曾经通过以下方式获得结果,但最终变得非常缓慢
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
我在上面的评论中指出,这似乎是一种超类型-子类型关系的情况,但是,由于更改数据库结构可能是超出此问题范围的决定,因此我将专注于提供解决方案你现在的情况。
然后,经过几次编辑,我决定包含一些
DDL
陈述和我对您的数据库结构的假设的简要描述,希望通过这种方式,我的答案及其涉及的查询将更容易理解。了解情况和假设
DDL
正如我所理解的那样,
type_a
可能type_b
是两种不同的类型,reading
或者measurement
您正在为每种类型收集device.
这样,虽然我不完全确定
type_a.type_a_id
and列的含义,但我假设它们在每个相应的表中type_b.type_b_id
都是某种sequential_number
或row_number
或。record_identifier
同样,列type_a.stats_time
和type_b.stats_time
是device
发布某种reading
.我还假设
type_a.device_id
并且type_b.device_id
是引用device
表的外键,而表又将列device.device_id
用作某种sequential_number
或row_number
或record_identifier
您已定义为主键的列。在描述了我对事态的理解之后,请注意我并不是在暗示这是最佳结构(因为我自然不熟悉真实场景,它可能缺乏规范化、完整性等),我是只是根据您提供的数据样本和查询做出一些假设,以便为您的具体情况提供可能的解决方案。所以,这里是推测
DDL
:初步提案
然后,这是我提交的第一个查询,在保留原始想法的同时,已重新格式化并适应了
DDL
后来添加的结构:如您所见,我正在使用COALESCE()函数,仅当列
type_a.stats_time
包含NULL
值时,才会“打印”列的值type_b.stats_time
,并以类似的方式处理type_a.status
andtype_b.status
列。后续提案
第一种方法
现在,重新阅读您的问题并经过一些评论互动后,我知道您真正想要的是获得一个仅包含两行的结果集——一行包含与最新值对应的列,另一行包含与最新值
type_a.stats_time
相关的列type_b.stats_time
——。因此,我建议您使用以下查询,该查询也从上述DDL
建议中检索数据:请注意UNION运算符的使用,它的目的是将(基于最新列值,通过WHERE 子句中的子查询中的MAX()函数获得)的最新行与最新行组合在一个结果集中行中(同样,基于最新的列值,也通过 WHERE 子查询中的子查询中的 MAX() 函数获得)。
type_a
stats_time
type_b
stats_time
第二种方法
您还可以尝试使用此备用查询,它使用ORDER BY和LIMIT子句根据
stats_time
每个相应 SELECT 语句中的列对每个组合结果集进行排序。一旦您比较了所有建议方法的性能,就很容易定义哪一种最适合您的需求。此外,如果其中一个解决了您的问题,那么您可以将其设置为
VIEW
,这样将来的数据检索将更容易获得。关于查询的速度性能方面,您可以通过特别注意 apropiate 列中的索引定义来开始细化这些问题,例如
type_a.stats_time
和type_b.stats_time
。我认为它分为两个步骤:
JOIN
或UNION
两张桌子。步骤 1 是groupwise max的变体:
这可能对性能有益:
TableB
和同上signal
。手动运行它们,看看我是否正确。您的示例没有显示两者
signal
和都noise
存在的情况device_id
。我会假设情况确实如此,因此UNION
:第2步: