0

我有一张表格:

创建表消息(
    id VARCHAR(40),
    src VARCHAR(40),
    目标 VARCHAR(40),
    时间 TIMESTAMP 默认 CURRENT_TIMESTAMP
);

我想编写一个查询,它将返回所有 id 的列表(src 或 dest 字段)以及对应于最新消息的消息 id。我不太明白如何以GROUP BY这种方式使用。此外,此查询需要快速(这就是为什么我不想简单地合并两个查询:一个用于 src,一个用于 dest)。但归根结底,性能是关键,不管它是如何完成的。

样本数据:

id、src、dest、时间
0, 0, 1, '2012-10-19 01:15:15'
1, 1, 0, '2012-10-20 01:15:15'
2, 0, 1, '2012-09-19 01:15:15'
3, 1, 0, '2012-04-20 01:15:15'
4, 2, 1, '2013-04-20 01:15:15'
5, 1, 0, '2012-04-20 01:15:15'

预期输出:

身份证,人
1, 0
4, 1
4, 2

当前查询:

SELECT m1.id,m1.src AS person FROM Messages m1 WHERE m1.time IS (SELECT MAX(time) FROM Messages m2 WHERE m2.src=m1.src OR m2.dest=m1.src)
联盟
SELECT m1.id,m1.dest AS person FROM Messages m1 WHERE m1.time IS (SELECT MAX(time) FROM Messages m2 WHERE m1.dest=m2.dest OR m1.dest=m2.src)

但是,对于具有 5163 行的表,这需要 19.99 秒。该查询有 26,661,730 步。

4

1 回答 1

1

我怀疑您的查询的问题不是union相关的子查询,而是相关的子查询。这是一种使用技巧来获取与最大时间关联的 id 的方法。它将 id 附加到时间的末尾,然后应用max()函数:

select substr(MAX(maxtime||maxtimeid), 19) as id, person
from (select src as person, substr(MAX(sent||CAST(id as varchar(20))), 19) as maxtimeid, MAX(sent) as maxtime
       from Messages
       group by src
       union all
      select dest as person, substr(MAX(sent||CAST(id as varchar(20))), 19) as maxtimeid, MAX(sent) as maxtime
       from Messages
       group by dest
     )
group by person

尽管此查询具有聚合,但它没有连接。尝试一下,看看你是否能获得更好的性能。请注意,我没有对此进行测试,因此可能存在小的语法错误。

我不知道 SQLite 中联合与外连接的相对性能。但是,您也可以将其表述为:

select (case when src.maxtime > dest.maxtime or dest.maxtime is null
             then src.maxtimeid
             else dest.maxtimeid
        end) as id,
       coalesce(src.person, dest.person) as person
from (select src as person, substr(MAX(sent||CAST(id as varchar(20))), 19) as maxtimeid, MAX(sent) as maxtime
       from Messages
       group by src
      ) src full outer join
      (select dest as person, substr(MAX(sent||CAST(id as varchar(20))), 19) as maxtimeid, MAX(sent) as maxtime
       from Messages
       group by dest
     ) dest
     on src.person = dest.person
于 2012-12-20T19:21:36.097 回答