保持行不在GROUP BY中重复计算

ldr*_*drg 5 sql postgresql join aggregate-functions

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

请注意,句号表可以指一个可变的时间范围 - 可能是整个赛季,可能是几场比赛或一场比赛.对于给定的团队和年份,所有期间行代表独有的时间范围.

我写了一个查询,它连接表并使用GROUP BY periods.year来汇总一个季节的分数(参见sqlfiddle).但是,如果一名教练在同一年有两个职位,GROUP BY将计算两次同一时期的排名.当教练担任两个职位但仍总结一年由多个时期组成的时期时,我怎么能抛弃重复数据呢?如果有更好的方法来制作模式,如果你向我指出,我也会很感激.

Erw*_*ter 8

潜在的问题(加入与多个匹配多个表)在此紧密相关的答案解释:

要修复,我首先简化了您的查询:

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;
Run Code Online (Sandbox Code Playgroud)

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

  • coach只要不使用SELECT列表中的列,就没有必要加入表.我完全删除了它并WHEREwhere pp.coach = 1.

  • 你不需要COALESCE.NULL在聚合函数中忽略值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;
Run Code Online (Sandbox Code Playgroud)
  • 在加入之前单独汇总头寸和期间.

  • 第一个子查询列表中,只需使用一次即可定位一次DISTINCT.

  • 第二个子查询中

    • GROUP BY period,因为教练每个时期可以有多个职位.
    • JOIN以期数据说,然后汇总得到的款项.

SQL小提琴.