繁体   English   中英

不使用join获取sql查询结果

[英]Get sql query result without using join

我在桌子下面有球员,比赛。

player_id | group_id
 -----------+----------
 20       |   2
 30       |   1
 40       |   3
 45       |   1
 50       |   2
 65       |   1

match_id | first_player | second_player | first_score | second_score
 ----------+--------------+---------------+-------------+--------------
 1       |    30        |       45      |      10     |     12
 2       |    20        |       50      |      5      |     5
 13      |    65        |       45      |      10     |     10
 5       |    30        |       65      |      3      |     15
 42      |    45        |       65      |      8      |     4

期望的结果:

group_id | winner_id
 ----------+-----------
   1     |  45
   2     |  20
   3     |  40

以下为案例:

  1. 在第 1 组中,获胜者是 45 号选手,总得分为 30 分。
  2. 在第 2 组中,两位玩家都获得了 5 分,但玩家 20 的 ID 较低并且是赢家。
  3. 第三组只有一名选手,虽然她没有参加任何比赛,但她是赢家。

我在下面用左连接写了查询,它满足所有 3 种情况。 但是我需要没有任何连接的查询。

以下查询供参考:

select group_id,player_id,totalScores from
 (select group_id,player_id,sum((
  case when player_id = first_player then first_score
   when player_id = second_player then second_score
   end
)) as totalScores

from players p
left join matches m on (p.player_id = m.first_player or p.player_id = m.second_player)

group by group_id,player_id
order by group_id,totalScores desc,player_id ) as temp
group by group_id
order by group_id,totalScores desc,player_id

您的查询无效。 在主查询中,您仅按 group_id 分组,但选择了 player_id 和 totalScores。 哪个player_id? 哪些总分? 每个 group_id 可以有很多。 MySQL 应该在此处引发错误,如果没有,则表明您正在使用 MySQL 臭名昭著的作弊模式,该模式会在此类列上静默应用ANY_VALUE函数。 不要那样做。 您会得到任意选择的值,这些值甚至可以来自不同的行。 在 MySQL 中,总是

SET sql_mode = 'ONLY_FULL_GROUP_BY';

为了不被允许写无效的查询。

除此之外,您在子查询中有一个ORDER BY子句。 无法对子查询进行排序,事实上,某些 DBMS 会在此处引发错误。 根据定义,子查询结果是无序数据集。

如果在 MySQL 作弊模式下运行,您的查询会为每个 group_id 选择一行,其中每一行都是任意选择的 player_id 和任意选择的总分。 这不是你想要的。

这是正确解决任务的查询。 它按照您的查询加入表格,但随后按 group_id 和ROW_NUMBER对玩家进行排名。 最后它显示了每组排名最高的玩家。

with scores as
(
  select
    p.group_id,
    p.player_id,
    coalesce(sum(case when player_id = first_player then first_score else second_score end), 0) as score
  from players p
  left join matches m on p.player_id in (m.first_player, m.second_player)
  group by p.group_id, p.player_id
)
, ranked as
(
  select group_id, player_id,
    row_number() 
      over(partition by group_id order by score desc, player_id) as rn
  from scores
)
select group_id, player_id
from ranked
where rn = 1
order by group_id;

(您可以立即排名,但我认为先计算总和然后在单独的步骤中排名更具可读性。)

正如你所说你不想加入(这似乎是一个非常奇怪的请求)并且你只需要比赛表中球员的总分,你可以用球员选择子句中的子查询替换外部连接:

with scores as
(
  select
    group_id,
    player_id,
    (
      select coalesce(sum(case when player_id = first_player then first_score else second_score end), 0)
      from matches m
      where p.player_id in (m.first_player, m.second_player)
    ) as score
  from players p
)

演示: https ://dbfiddle.uk/PxP_gMXI

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM