2017-10-15 17 views
0

各ユーザーには難易度の高いタスクが多数存在するため、1対多の関係になります。私は一度各ユーザを一度に見せているリストを、一番難しい課題に照会したいと思っています。1対多の左結合の集計関数を使用したSQLクエリ

ユーザーテーブル:user_idを、ユーザ名

タスクテーブル:私は

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 

のようなクエリを試してみたのuser_id、TASK_ID、タスク名、難易

は、しかし、私はnot in GROUP BY clauseエラーを取得しますこれを実行する。

+0

をお試しください各ユーザー、および各タスクの最大難易度を示します。どのDBMSを使用していますか? 1人のユーザーが同じ(最大)困難な2つのタスクを持つ状況を、どのように処理する必要がありますか? –

+0

ここをクリック:http://sqlfiddle.com/#!9/03994e/1 はうまく動作しているようです – Riad

+1

@Riad - OPはDBMSを使用しています。 '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 
     ) 

これは、よりパフォーマンスになります。ユーザーは、その後、同じ難易度を持つ2つの最大のタスクを持っている場合

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 

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 

は、これらのクエリの両方が、次のデータセットを返しますクエリにはそのユーザーの2つの行が含まれます。

このSQLのクエリプランを示すと、2番目のクエリのコストは1番目のクエリのコストの約2倍になります。 where句にmax()があることは、from句にmax()を配置するより効率的と思われます。私はあなたの実際のデータで両方の方法を試してみて、クエリプラン/コストがあなたにとって何であるかを見てみましょう。

+0

ありがとうございます。私のデータセットは、テーブルあたり1000行未満で、5列未満ではあまり大きくありません。私はまだ将来の校正のためにもっとパフォーマンスの良いソリューションを使いました。 – miljinx

0

私はあなたが一人のユーザが同じ最大の難しさを持つ2つのタスクを持っていない、あなたはこのような何かを行うことができますと仮定すると、この

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

それがために、すべてのタスク名が表示されますので、あなたの規定の目標は、(各ユーザーを示し、彼らの最も困難な作業)、)(シンプル `最大で行わ`と `グループby`することはできません

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;