2

ステータスが「OPEN」で、最後のメッセージが特定のグループのユーザーによって投稿されなかったすべてのスレッドのリストを返すメッセージングシステムのSQLクエリを作成しようとしています。

クエリに関係するテーブルは次のとおりです。

threads
-------
threadId
timestamp
subject
status
clientId

messages
--------
messageId
userId
messagebody
timestamp
threadId

users
-----
userId
username
groupId

現在のクエリは次のとおりです。

SELECT threadId, timestamp, subject, status, clientId 
FROM threads
WHERE status='OPEN' 
ORDER BY timestamp DESC

これは正常に機能します。しかし、新しい要件があります。スレッドの最後のメッセージがgroupId1のユーザーによって投稿された場​​合、そのメッセージは結果セットに含まれないはずです。

必要な情報を含めるのは簡単です。

SELECT threadId, timestamp, subject, status, clientId 
FROM threads
INNER JOIN messages USING(threadId)
INNER JOIN users USING(userId)
WHERE status='OPEN' 
GROUP BY threadId
ORDER BY timestamp DESC

しかし、特定のグループ内でmessages.userId最も高いスレッドに基づいてスレッドをフィルターで除外するクエリを取得する方法がわからないため、この時点で行き詰まります。timestamp私はHAVINGすべての集計関数を調べましたが、何も法案に適合しないようです。

編集

はっきりしていなかったかもしれないので、例を挙げて説明します。

データの例を次に示します。

スレッド

threadId | timestamp | subject | status | clientId
--------------------------------------------------
1        | 1         | One     | OPEN   | 1
2        | 10        | Two     | OPEN   | 4
3        | 26        | Three   | OPEN   | 19
4        | 198       | Four    | OPEN   | 100

メッセージ

messageId | userId | messagebody | timestamp | threadId
-------------------------------------------------------
1         | 3      | Hello, World| 1         | 1
2         | 1      | Hello       | 3         | 1
3         | 1      | ^&%&6       | 10        | 2
4         | 2      | Test        | 12        | 2
5         | 4      | Hi mum      | 26        | 3
6         | 1      | More tests  | 100       | 4

ユーザー

userId | username | groupId
---------------------------
1      | Gareth   | 1
2      | JimBob   | 2
3      | BillyBob | 2
4      | Bod      | 3

この例では、ユーザーGareth(グループ1のメンバー)が最後に投稿するため、データセットスレッド1と4をクエリから削除する必要があります(threadId1のmessageId2とthreadId4のmessageId5)。したがって、結果セットには、スレッド2および3のスレッドデータ(threadId、timestamp、subject、status、およびclientId)のみが含まれている必要があります。

このテストデータ用にSQLfiddleを作成しました。

誰かが私をここで正しい方向に向けることができますか?

4

2 に答える 2

2

あなたがこれを望んでいるように聞こえます:

SELECT threadId, timestamp, subject, status, clientId 
FROM threads t
INNER JOIN messages m
  ON t.threadId = m.threadId
INNER JOIN users u
  ON m.userId = u.userId
  and u.groupId != 1  --placed the groupId filter here.
WHERE status='OPEN' 
GROUP BY threadId
ORDER BY timestamp DESC

編集、これはあなたが必要なものをあなたに与えるように見えます:

SELECT t.threadId, 
  t.timestamp, 
  t.subject, 
  t.status, 
  t.clientId
FROM threads t
INNER JOIN messages m
  ON t.threadId = m.threadId
INNER JOIN users u
  ON m.userId = u.userId
WHERE status='OPEN' 
  AND NOT EXISTS (select t1.threadid
                  FROM threads t1
                  INNER JOIN messages m
                    ON t1.threadId = m.threadId
                  INNER JOIN users u
                    ON m.userId = u.userId
                  where u.groupid = 1
                     and t.threadid = t1.threadid)
ORDER BY timestamp DESC

SQL FiddlewithDemoを参照してください

于 2012-09-14T12:05:26.703 に答える
1

クエリに追加LIMIT 1することで問題は解決しますか?

SELECT threadId, timestamp, subject, status, clientId  
FROM threads 
INNER JOIN messages USING(threadId) 
INNER JOIN users USING(userId) 
WHERE status='OPEN'  
GROUP BY threadId 
ORDER BY timestamp DESC 
LIMIT 1

または、where句を次のように変更します

WHERE status='OPEN' and groupID<>1

これがあなたの欲しいものだと思いますか?

select * from threads
where threadId not in
(
    select messages.threadId
    from messages
        inner join (select threadId, MAX(timestamp) maxtime from messages group by threadId) t
            on messages.threadId = t.threadId
            and messages.timestamp = t.maxtime
    where messages.userId=1
)   
于 2012-09-14T12:03:32.860 に答える