2012-12-20 50 views
0

我有以下形式的表:如何按SQL中兩列之一進行分組?

CREATE TABLE Messages ( 
    id VARCHAR(40), 
    src VARCHAR(40), 
    dest VARCHAR(40), 
    time TIMESTAMP DEFAULT CURRENT_TIMESTAMP 
);

我想寫與對應於最新的消息的消息ID一起的查詢將返回所有的ID列表(無論是SRC或DEST字段) 。我不太明白如何以這種方式使用GROUP BY。此外,這個查詢需要很快(這就是爲什麼我不想簡單地結合兩個查詢:一個用於src和一個用於dest)。但最終,性能是關鍵,無論它是如何完成的。

樣本數據:

 
id, src, dest, time 
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' 

預期輸出:

 
id, person 
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) 
UNION 
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) 

然而,這需要19.99sec與5163行的表。該查詢有26,661,730步。

+3

你應該發佈你已經嘗試過。這給了我們更多的細節,並且我們可以通過稍微修改來複制粘貼代碼來快速給出答案。 – nawfal

+3

或者rahter向我們展示一些示例數據,請沿着預期的輸出:)。 – bonCodigo

+1

關於表現,您的索引列是什麼? – anAgent

回答

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

我更正了sql,但確實運行得更快:在36.35毫秒。 – chacham15

+0

請注意,通過使用'union all'而不是'union',你可以調整更多的性能。我還給出了獲取相同信息的另一種方式。 –

+0

SQLite不支持外部連接 – chacham15

相關問題