0

我的问题的简化版本。我有 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 表中在 Codes 表中没有关联代码的所有行,以及在 Codes 表中具有相同代码的行中的最高分数。

所需的输出如下所示。分数 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

我希望这是有道理的。我认为这将是一件容易的事,但它让我感到困惑。我已经检查了 [greatest-n-per-group] 标记问题的负载,并且大多数似乎在执行 GROUP BY 和子选择时只引用一个表并且没有帮助。

非常感谢。

4

2 回答 2

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)for each code,您可以使用:

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;

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

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

请参阅SQL Fiddle with Demo

code如果值是空字符串而不是,则作为旁注进行编辑null,然后您可以更改要使用的代码''(请参阅演示)。

于 2013-05-23T17:23:31.523 回答
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
于 2013-05-23T17:27:37.223 回答