具有聚合函数的SQL查询在一对多关系的左连接上

时间:2017-10-15 06:12:52

标签: sql join aggregate one-to-many

我有一对多的关系,每个用户都有很多任务,按难度评分。我想查询一个列表,显示每个用户一次以及他们最困难的任务。

用户表: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错误。

3 个答案:

答案 0 :(得分:0)

我认为你正在寻找类似的东西

private void button1_Click(object sender, EventArgs e)
{
    foreach (Control ctrl in Flatten(this))
    {
        if (ctrl is Panel)
        {
            (ctrl as Panel).BackColor = Color.FromArgb(214, 219, 233);
        }
        if (ctrl is GroupBox)
        {
            (ctrl as GroupBox).BackColor = Color.FromArgb(214, 219, 233);
        }
    }
}

static IEnumerable<Control> Flatten(Control c)
{
    yield return c;

    foreach (Control o in c.Controls)
    {
        foreach (var oo in Flatten(o))
            yield return oo;
    }
}

答案 1 :(得分: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的查询计划表示第二个查询的成本几乎是第一个查询成本的两倍。在max()子句中使用where似乎比在max()子句中放置from更有效。我会在您的实际数据上尝试两种方式,并查看查询计划/成本对您的影响。

答案 2 :(得分: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;