0

我有一个以下模式的表:

+----+--------+----------------------------+----------------------------+
| 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 byhaving

select id, any_value(`updated_timestamp`), any_value(amount) from transactions group by `id` having max(`updated_timestamp`);
4

1 回答 1

2

在 MySQL 中执行这样的查询时有两个(好的)选项。您已经尝试过一种选择。这是另一个:

SELECT t1.id, 
       t1.amount, 
       t1.created_timestamp, 
       t1.updated_timestamp 
FROM   transactions AS t1 
LEFT OUTER JOIN transactions later_transactions
       ON later_transactions.id = t1.id 
       AND later_transactions.last_transaction_time > t1.updated_timestamp
WHERE  later_transactions.id IS NULL

这些方法是文档中的方法,也是我工作中基本每天都会用到的方法。哪一个最有效取决于多种因素,但通常情况下,如果一个很慢,另一个会很快。

此外,正如草莓在评论中指出的那样,您需要一个关于(id,updated_timestamp). 有单独的索引idupdated_timestamp不等价。

为什么是综合指数?

请注意,索引只是表中数据的副本。在许多方面,它的工作原理与表格相同。因此,创建索引就是创建表数据的副本,RDBMS 可以使用该副本以更有效的方式查询表的信息。

just 上的索引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-Trees。可以说,找到第一条(或最后一条)记录很容易。

尝试以下操作:

ALTER TABLE transactions
ADD INDEX `LatestTransaction` (`id`,`updated_timestamp`)

然后查看您的原始查询或我的备用查询是否更快。可能两者都比没有索引要快。随着表的增长或选择语句的更改,它可能会影响这些查询中的哪一个更快,但无论您使用哪个版本的查询,索引都会提供最大的性能提升。

于 2018-01-09T15:18:58.417 回答