我得到了一个包含以下模式的表:
+----+--------+----------------------------+----------------------------+
| id | amount | created_timestamp | updated_timestamp |
+----+--------+----------------------------+----------------------------+
| 1 | 1.00 | 2018-01-09 12:42:38.973222 | 2018-01-09 12:42:38.973222 |
+----+--------+----------------------------+----------------------------+
来,给你 id = 1
,可以有多个金额条目。我想提取最后添加的条目及其相应的数量,按id分组。
我在self表上编写了一个具有内部联接的工作查询,如下所示:
SELECT t1.id,
t1.amount,
t1.created_timestamp,
t1.updated_timestamp
FROM transactions AS t1
INNER JOIN (SELECT id,
Max(updated_timestamp) AS last_transaction_time
FROM transactions
GROUP BY id) AS latest_transactions
ON latest_transactions.id = t1.id
AND latest_transactions.last_transaction_time =
t1.updated_timestamp;
我认为内部连接是一种过度杀伤力,可以用更优化/更高效的查询来代替。我已经用编写了以下查询 where
, group by
,和 having
但它不起作用。有人能帮忙吗?
select id, any_value(`updated_timestamp`), any_value(amount) from transactions group by `id` having max(`updated_timestamp`);
1条答案
按热度按时间idv4meu81#
在mysql中执行这样的查询时,有两个(好的)选项。您已经尝试了一个选项。另一个是:
这些方法是文档中的方法,也是我基本上每天在工作中使用的方法。哪一个效率最高取决于多种因素,但通常情况下,如果一个慢,另一个就会快。
另外,正如草莓在评论中指出的,你需要一个关于
(id,updated_timestamp)
. 有单独的索引id
以及updated_timestamp
不是等价的。为什么是综合指数?
请注意,索引只是表中数据的副本。在许多方面,它的工作原理与表相同。因此,创建索引就是创建表数据的副本,rdbms可以使用该副本以更高效的方式查询表信息。
一个索引
updated_timestamp
将创建包含updated_timestamp
作为第一列,该数据将被排序。它还将在每个索引行中包含一个隐藏的行id值(作为主键),以便它可以使用该值在实际表中查找整行。这在这个查询中有什么帮助(任何一个版本)?如果我们只想要最新的(或最早的)
updated_timestamp
总的来说,它会有所帮助,因为它可以检查索引中的第一个或最后一个记录。但既然我们每个人都想要最新的id
,此索引无效。只是一个索引怎么样
id
. 我们有一份id
列,按id
列,行id附加到索引中的每一行。这对查询有什么帮助?它没有,因为它甚至没有
updated_timestamp
列作为索引的一部分,因此甚至不会考虑使用此索引。现在,考虑一个综合指数:
(id,updated_timestamp)
.这将使用
id
列,排序,然后是第二列updated_timestamp
也包括在内,并且在每个id
.这与电话簿(如果人们仍将这些东西用作镇纸以外的东西)按姓氏和名字排序的方式相同。
因为行是这样排序的,所以mysql可以为每一行
id
,在给定的id
. 它知道那个记录包含了最高的updated_timestamp
值,因为索引是如何定义的。所以,它只需要为每一行查找一行
id
那是存在的。太快了。进一步解释为什么会占用更多的空间,但如果你愿意,你可以自己研究,只要看看b-树。可以说,找到第一个(或最后一个)记录很容易。请尝试以下操作:
然后看看您的原始查询还是我的备用查询速度更快。很可能两者都比没有索引要快。随着表的增长,或者select语句的更改,它可能会影响这些查询中哪个更快,但是索引将提供最大的性能提升,而不管您使用哪个版本的查询。