2017-10-15 129 views
0

我有一對多的關係,每個用戶都有很多任務,這些任務按難度分級。我想查詢一個列表,顯示每個用戶以及他們最困難的任務。左側具有聚合函數的SQL查詢加入一對多關係

用戶表:user_ID的,用戶名

任務表:USER_ID,TASK_ID,TASKNAME,難度

我已經試過像

SELECT u.user_id, u.username, t.task_id, t.taskname, MAX(t.difficulty) 
FROM users u 
LEFT JOIN tasks t ON u.user_id = t.user_id 
GROUP BY u.user_id 

但是查詢時,我得到的not in GROUP BY clause錯誤時運行這個。

+0

你的既定目標(顯示每個用戶以及他們最困難的任務),不能用簡單的'最大()來完成'和'組by',因爲它會顯示所有任務名稱每個用戶以及每個任務的最大難度。你使用的是什麼DBMS?您如何處理一個用戶有兩個任務都是相同(最大)難度的情況? –

+0

看到這裏:http://sqlfiddle.com/#!9/03994e/1 似乎工作正常 – Riad

+1

@Riad - 該OP是使用一個DBMS,強制'select'子句中的所有非聚合字段也是在'group by'子句中,sqlfiddle不執行該限制。我懷疑OP正在使用SQL Server。 –

回答

0

假設一個用戶沒有使用相同的最大困難兩項任務,你可以做這樣的事情。雖然這不是很高效。它可以在小數據集上正常工作,但如果數據集非常大,則應重新設計。希望它能讓你指出正確的方向。

declare @users table (user_id int, username varchar(10)) 
declare @tasks table (task_id int, user_id int, taskname varchar(24), difficulty int) 

insert into @users values 
(1, 'John'), 
(2, 'Sally'), 
(3, 'Sam') 

insert into @tasks values 
(1, 1, 'prepare grocery list', 1), 
(2, 1, 'do shopping', 2), 
(3, 1, 'cook food', 3), 
(4, 2, 'do shopping', 2), 
(5, 2, 'prepare grocery list', 1), 
(6, 3, 'cook food', 3) 

select u.user_id, u.username, t.task_id, t.taskname, t.difficulty 
from @users u 
     left join @tasks t on u.user_id = t.user_id 
where t.difficulty = (
     select max(x.difficulty) 
     from @tasks x 
     where t.user_id = x.user_id 
     ) 

這將是更好的性能:

select u.user_id, u.username, t.task_id, t.taskname, t.difficulty 
from @users u 
     left join @tasks t on u.user_id = t.user_id 
     inner join (
     select x.user_id, max(x.difficulty) as max_difficulty 
     from @tasks x 
     group by x.user_id 
     ) as y on t.user_id = y.user_id and t.difficulty = y.max_difficulty 

這兩個查詢返回以下數據集:

user_id  username task_id  taskname     difficulty 
----------- ---------- ----------- ------------------------ ----------- 
1   John  3   cook food    3 
2   Sally  4   do shopping    2 
3   Sam  6   cook food    3 

如果用戶有同樣的困難兩根最大的任務,那麼,查詢將包含該用戶的兩行。

儘管顯示此SQL的查詢計劃表示第二個查詢的開銷幾乎是第一個查詢開銷的兩倍。在where子句中使用max()似乎比將max()置於from子句中效率更高。我會在您的真實數據上嘗試這兩種方式,並查看查詢計劃/成本對您的影響。

+0

謝謝。我的數據集不是很大,每行少於1000行,少於5列。我仍然使用更高性能的解決方案來進行面向未來的解決方案。 – miljinx

0

我認爲你正在尋找這樣的事情

SELECT u.user_id, u.username, t.task_id, t.taskname,t.difficuilty 
FROM users u LEFT JOIN tasks t ON u.user_id = t.user_id 
INNER JOIN 
(
SELECT user_Id,Max(difficuilty) D FROM tasks GROUP BY user_id 
)Temp ON Temp.user_id = u.user_id ANDTemp.D = t.difficuilty 
GO 
0

嘗試

SELECT u.user_id, u.username, t.task_id, t.taskname, m.difficulty 
     FROM tasks t 
RIGHT JOIN (SELECT user_id, 
        MAX(difficulty) as difficulty 
       FROM tasks 
      GROUP BY user_id) m ON t.user_id = m.user_id 
          AND t.difficulty = m.difficulty 
LEFT JOIN users u ON t.user_id = u.user_id;