2011-09-18 23 views
1

我正在使用Android SQLite數據庫,並且我有一個包含消息的表。每封郵件都有一個ContactId。我需要獲得與每個ContactId相關的最新消息列表。SQLite查詢:爲每個不同的聯繫人選擇最新的行

我的查詢看起來像這樣至今:

SELECT * FROM messages GROUP_BY ContactId HAVING (COUNT(ContactId) = 1) ORDER_BY MessageTime DESC 

然而,當我運行查詢我得到這個異常:

near "ContactId": syntax error: , while compiling: SELECT * FROM messages GROUP_BY ContactId HAVING (COUNT(ContactId) = 1) ORDER_BY MessageTime DESC 

這裏的表定義的情況下,它可以幫助:

create table messages (_id integer primary key autoincrement, ContactId text not null, ContactName text not null, ContactNumber text not null, isFrom int not null, Message text not null, MessageTime int not null); 
+0

我使用的是一個StringBuilder類,因爲我在變量中有列名,但這就是它輸出的內容。 –

+0

我對HAVING語句感到困惑,你爲什麼要過濾一個1?如果你刪除它,它會工作嗎? –

+0

HAVING語句我用一個使用它作爲DISTINCT的替代品的例子,因爲這顯然只允許你選擇1列(或者我理解)。 –

回答

2

注意:我下面的答案似乎不工作的SQLite 3.7.5,我建議使用Larry建議的「JOIN」查詢。

你就近了。你需要做的是先排序所有的記錄,使用子查詢表,然後對它們進行分組。結果集中返回的值將來自每個組的最後一行。所以如果你想獲得新的消息,你實際上想讓更新的消息出現在底部。 「GROUP BY」已確保您爲每個ContactId獲得一行。

SELECT * FROM (SELECT * FROM messages ORDER BY MessageTime) GROUP BY ContactId 

不需要HAVING子句。我以前沒有使用它,但根據文檔,HAVING子句將丟棄不匹配的整個組,但它聽起來並不像您想要丟棄任何組,您希望每個ContactId的結果。

另請注意,「ORDER BY」或「GROUP BY」中沒有下劃線。

+0

你有一些文檔描述SQLite的這種非常不尋常的行爲嗎?我知道的唯一的其他數據庫允許非聚合列出現在SELECT中,而不是GROUP BY是MySQL,在這種情況下,選擇的列值是隨機的,而不是「最後一個」。如果你描述的行爲確實是SQLite的文檔化行爲,那麼這將非常有用。 –

+0

不幸的是,這種行爲似乎有點文件。我搜索了一會兒,沒有發現任何明確的內容。 實際上,當它將GROUP BY關鍵字描述爲「排序項」時,文檔看起來很明顯是錯誤的。例如,即使「MessageTime ASC」似乎是有效的「排序期限」,它也會拒絕「ORDER BY MessageTime ASC」。 – satur9nine

+0

我確實檢查過文檔,它說:「......它是針對組內單個任意選擇的行進行評估的,如果結果集中有多個非聚合表達式,則所有這些表達式都會被計算同一排。「所以這聽起來像你描述的行爲可能是不可靠的,並且不能保證所有版本。這是一個遺憾,因爲它看起來像一個真正有用的功能。 –

2

這裏有兩種方法來做到這一點。

這個查詢構建最近一段時間針對每個用戶的列表,然後入該回消息表得到的消息信息:

SELECT M1.* FROM messages M1 JOIN 
    (SELECT ContactId, MAX(MessageTime) AS MessageTime FROM messages GROUP BY ContactId) M2 
    ON M1.ContactID = M2.ContactID AND M1.MessageTime = M2.MessageTime; 

這個查詢做了略有不同。它會查看每條消息並詢問是否存在針對同一聯繫人的任何後續消息。如果沒有,該行必須是最近的那一行:

SELECT M1.* FROM messages M1 
    WHERE NOT EXISTS (SELECT * FROM M2 
     WHERE M2.ContactID = M1.ContactID AND M2.MessageTime > M1.MessageTime) 
+0

第一個查詢(連接查詢)具有線性性能O(n),而第二個查詢(存在查詢)具有二次性能O(n^2),這是一個巨大的差異。原因是在連接查詢中,連接中的兩個表中的每一個都是查詢,然後連接在結果上運行。在存在查詢中,子查詢依賴於主查詢,因此每個行都會重新執行。我強烈建議選擇連接查詢。感謝這兩個解決方案! – satur9nine

相關問題