簡體   English   中英

如何使用GROUP BY子句過濾SQL查詢

[英]How can I filter an SQL query with a GROUP BY clause

我正在嘗試為消息傳遞系統制定一個SQL查詢,該查詢將返回狀態為“OPEN”且其最后一條消息未由某個組中的用戶發布的所有線程的列表。

查詢中涉及的表是:

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

工作正常; 但我現在有一個新的要求 - 如果線程中的最后一條消息是由groupId為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

但此時我陷入困境,因為我無法弄清楚如何根據特定組中具有最高timestampmessages.userId來過濾掉線程的查詢。 我已經看過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

在此示例中,數據集線程1和4應從查詢中刪除,因為用戶Gareth (組1的成員)是最后一個發布給它們的(threadId 1中的messageId 2和threadId 4中的messageId 5)。 因此,結果集應該只包含線程2和3的線程數據(threadId,timestamp,subject,status和clientId)。

我為這個測試數據創建了一個SQLfiddle

任何人都能指出我在正確的方向嗎?

聽起來你想要這個:

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 Fiddle with Demo

在查詢中添加 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 ) 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM