7

这是我的架构和问题的基本内容:http ://sqlfiddle.com/#!1/72ec9/4/2

请注意,周期表可以引用可变的时间范围 - 它可能是整个赛季,可能是几场比赛或一场比赛。对于给定的团队和年份,所有期间行都代表唯一的时间范围。

我编写了一个查询,它连接表并使用 GROUP BY period.year 来汇总一个赛季的分数(参见 sqlfiddle)。但是,如果教练在同一年有两个职位,则 GROUP BY 将计算同一时期的行两次。当一名教练担任两个职位但仍然总结一年由多个时期组成的时期时,我该如何放弃重复?如果有更好的方法来执行架构,如果您向我指出,我也会很感激。

4

3 回答 3

10

此相关答案中解释了潜在问题(加入具有多个匹配项的多个表):

为了解决这个问题,我首先简化并格式化了您的查询:

select pe.year
     , sum(pe.wins)       AS wins
     , sum(pe.losses)     AS losses
     , sum(pe.ties)       AS ties
     , array_agg(po.id)   AS position_id
     , array_agg(po.name) AS position_names
from   periods_positions_coaches_linking pp
join   positions po ON po.id = pp.position
join   periods   pe ON pe.id = pp.period
where  pp.coach = 1
group  by pe.year
order  by pe.year;

产生与原始结果相同但不正确的结果,但更简单/更快/更易于阅读。

  • coach只要您不使用列表中的列,就没有必要加入表格SELECT。我将其完全删除并用 替换了WHERE条件where pp.coach = 1

  • 你不需要COALESCENULL聚合函数中的值被忽略sum()。无需替代0

  • 使用表别名使其更易于阅读。

接下来,我这样解决了你的问题:

SELECT *
FROM  (
   SELECT pe.year
        , array_agg(DISTINCT po.id)   AS position_id
        , array_agg(DISTINCT po.name) AS position_names
   FROM   periods_positions_coaches_linking pp
   JOIN   positions                         po ON po.id = pp.position
   JOIN   periods                           pe ON pe.id = pp.period
   WHERE  pp.coach = 1
   GROUP  BY pe.year
   ) po
LEFT   JOIN (
   SELECT pe.year
        , sum(pe.wins)   AS wins
        , sum(pe.losses) AS losses
        , sum(pe.ties)   AS ties
   FROM  (
      SELECT period
      FROM   periods_positions_coaches_linking
      WHERE  coach = 1
      GROUP  BY period
      ) pp
   JOIN   periods pe ON pe.id = pp.period
   GROUP  BY pe.year
   ) pe USING (year)
ORDER  BY year;
  • 在加入之前分别汇总职位和期间。

  • 第一个子查询 po列表位置只有一次array_agg(DISTINCT ...)

  • 第二个子查询 pe...

    • GROUP BY period,因为教练每个时期可以有多个职位。
    • JOIN之后的周期数据,然后聚合得到总和。

db<>fiddle here
sqlfiddle

于 2012-10-03T19:19:17.137 回答
2

在您的情况下,最简单的方法可能是划分职位:

select periods.year as year,
       sum(coalesce(periods.wins, 0))/COUNT(distinct positions.id) as wins,
       sum(coalesce(periods.losses, 0))/COUNT(distinct positions.id) as losses,
       sum(coalesce(periods.ties, 0))/COUNT(distinct positions.id) as ties,
       array_agg(distinct positions.id) as position_id,
       array_agg(distinct positions.name) as position_names
from periods_positions_coaches_linking join
     coaches
     on coaches.id = periods_positions_coaches_linking.coach join
     positions
     on positions.id = periods_positions_coaches_linking.position join
     periods
     on periods.id = periods_positions_coaches_linking.period
where coaches.id = 1
group by periods.year
order by periods.year;

位置的数量可以衡量胜负和平局,因此将其分开会调整计数。

于 2012-10-03T19:23:48.490 回答
2

如此处distinct所示使用

代码:

select periods.year as year,
sum(coalesce(periods.wins, 0)) as wins,
sum(coalesce(periods.losses, 0)) as losses,
sum(coalesce(periods.ties, 0)) as ties,
array_agg( distinct positions.id) as position_id,
array_agg( distinct positions.name) as position_names

from periods_positions_coaches_linking

join coaches on coaches.id = periods_positions_coaches_linking.coach
join positions on positions.id = periods_positions_coaches_linking.position
join periods on periods.id = periods_positions_coaches_linking.period

where coaches.id = 1

group by periods.year, positions.id
order by periods.year;
于 2012-10-03T19:21:31.257 回答