2011-09-18 12 views
1

私はAndroidのSQLiteデータベースを使用しています。メッセージが入ったテーブルがあります。各メッセージのメッセージはContactIdです。各ContactIdに関連付けられた最新のメッセージのリストを取得する必要があります。SQLiteクエリ:別個の連絡先ごとに最新の行を選択

私のクエリは、これまでに次のようになります。

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); 
を:

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

ここでそれが助け場合には、テーブル定義があります:私は、クエリを実行すると

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

をしかし、私はこの例外を取得します

+0

変数に列名があるので、私はStringBuilderクラスを使用していますが、それは出力します。 –

+0

HAVINGステートメントで混乱していますが、なぜ1のカウントでフィルタリングしていますか?あなたはそれを削除する場合は動作しますか? –

+0

HAVINGステートメントは、DISTINCTの代わりに使用する例を取り上げました。明らかに1列しか選択できないためです(または理解しています)。 –

答えて

2

注:私の答えは以下の通りです: SQLite 3.7.5のうち、Larryが提案した "JOIN"クエリを使用することをお勧めします。

あなたは近くにいます。あなたがする必要があるのは、サブクエリテーブルを使用してすべてのレコードを最初に並べ替え、グループ化することです。結果セットに返される値は、各グループの最後の行からのものになります。したがって、新しいメッセージを取得しようとすると、より新しいメッセージが下部に表示されます。 "GROUP BY"はすでにContactIdごとに1行を取得することを保証します。

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

残念ながら、ドキュメントはこの動作では少しおかしいと思われます。私はしばらくの間検索し、何も明白でないことを発見しました。 実際には、「ordering-term」の後にGROUP BYキーワードが記述されている場合、ドキュメントは間違っているようです。例えば、 "MessageTime ASC"が有効な "発注用語"であると思われるとしても、それは "ORDER BY MessageTime ASC"を拒絶する。 – satur9nine

+0

私はドキュメントをチェックして、「グループ内から任意に選択された1つの行に対して評価されます」結果セットに複数の非集計式がある場合、そのような式はすべて評価されます同じ行。つまり、あなたが記述した動作が信頼できない可能性があり、確実にバージョン間で保証されていないように思えます。それは真に有用な機能のように思えるので、同情です。 –

2

ここには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

第1のクエリ(結合クエリ)は線形性能O(n)を有するが、第2のクエリ(存在クエリ)は2次性能O(n^2)を有する。この理由は、結合クエリでは、結合内の2つのテーブルのそれぞれがクエリであるため、結果に対して結合が実行されるためです。存在問合せでは、副問合せは主問合せに依存し、したがって各行に対して再実行されます。結合クエリを選択することを強くお勧めします。これら両方のソリューションに感謝します! – satur9nine

関連する問題