Mysql - 返回在另一个表中没有关联记录的行加上具有记录的max

时间:2013-05-23 17:10:39

标签: mysql greatest-n-per-group

我的问题的简化版本。我有2张桌子:

成绩:

id  code_id score
1   11     100
2   12     20
3   13     40
4   14     70
5   15     90
6   16     10
7   17     30
8   18     50

代码:

id   code
11   
12
13
14
15
16    BBB
17    BBB
18    BBB

我需要生成一个Mysql SELECT查询,该查询将返回Scores表中代码表中没有相关代码的所有行,以及代码表中具有相同代码的行中的最高分数。

所需输出如下所示。分数ID为1-5,因为它们没有关联的代码,但只选择了ID 8,因为它是所有BBB代码分数的最高值。

id  code_id score
1   11     100
2   12     20
3   13     40
4   14     70
5   15     90
8   18     50

我希望这是有道理的。我认为这将是一个简单的,但它让我感到困惑。我检查了[最大n组]标记问题的负载,大多数似乎只在执行GROUP BY和子选择时引用一个表而没有帮助。

非常感谢。

2 个答案:

答案 0 :(得分:2)

也许我遗漏了您的要求但在两次查询之间使用UNION ALL可能更容易。

要获取null表中具有codes代码的行,您可以使用:

select s.id, s.code_id, s.score
from scores s
where exists (select id
              from codes c
              where s.code_id = c.id
                and c.code is null)

然后,为了获得每个max(score)的{​​{1}},您可以使用:

code

最后,您可以使用UNION ALL组合两个查询:

select s.id, s.code_id, s.score
from scores s
inner join codes c
  on s.code_id = c.id
inner join
(
  select c.code, max(s.score) score
  from scores s
  inner join codes c
    on s.code_id = c.id
  where c.code is not null
  group by c.code
) m
  on c.code = m.code
  and s.score = m.score;

请参阅SQL Fiddle with Demo

如果select s.id, s.code_id, s.score from scores s where exists (select id from codes c where s.code_id = c.id and c.code is null) union all select s.id, s.code_id, s.score from scores s inner join codes c on s.code_id = c.id inner join ( select c.code, max(s.score) score from scores s inner join codes c on s.code_id = c.id where c.code is not null group by c.code ) m on c.code = m.code and s.score = m.score group by c.code //To remove duplicates where the code and the score are equal 值为空字符串而不是code,则编辑为旁注,然后您可以更改代码以使用null(请参阅demo)。

答案 1 :(得分:1)

试试这个:

select s.*
from scores s join
     (select coalesce(code, cast(id as varchar(32))) as codeid, max(id) as id
      from codes c
      group by  coalesce(code, cast(id as varchar(32)))
     ) c
     on s.code_id = c.id;

这个想法是总结代码表以获得每个代码的最大id,以及代码为NULL的每个id的单行。

以下显示结果(道歉,这是针对SQL Server但代码在那里非常相似):

declare @scores table (id int identity(1, 1), code_id int, score int);

insert into @scores(code_id, score)
    select 11, 100 union all
    select 12, 20 union all
    select 13, 40 union all
    select 14, 70 union all
    select 15, 90 union all
    select 16, 30 union all
    select 17, 30 union all
    select 18, 50;

declare @codes table (id int, code varchar(3));

insert into @codes(id, code)
    select 11, NULL union all
    select 12, NULL union all
    select 13, NULL union all
    select 14, NULL union all
    select 15, NULL union all
    select 16, 'BBB' union all
    select 17, 'BBB' union all
    select 18, 'BBB';   

select s.*
from @scores s join
     (select coalesce(code, cast(id as varchar(32))) as codeid, max(id) as id
      from @codes c
      group by  coalesce(code, cast(id as varchar(32)))
     ) c
     on s.code_id = c.id