以下是我的架构和问题的基本内容:http://sqlfiddle.com/#!1/72ec9/4/0
请注意,句号表可以指一个可变的时间范围 - 可能是整个赛季,可能是几场比赛或一场比赛。对于给定的团队和年份,所有期间行都代表独有的时间范围。
我写了一个查询,它连接表并使用GROUP BY periods.year来汇总一个季节的分数(参见sqlfiddle)。但是,如果一名教练在同一年有两个职位,GROUP BY将计算两次同一时期的排名。当教练担任两个职位但仍总结一年由多个时期组成的时期时,我怎么能抛弃重复数据呢?如果有更好的方法来制作模式,如果你向我指出,我也会很感激。
答案 0 :(得分: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;
产生与原始相同的错误的结果,但更简单/更快/更容易阅读。
只要您不使用coach
列表中的列,就无需加入表SELECT
。我将其完全删除,并将WHERE
条件替换为where 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;
在加入之前单独汇总位置和期间。
在第一个子查询列表中,只需使用DISTINCT
进行一次排名。
在第二个子查询
中GROUP BY period
,因为教练每个时期可以有多个职位。JOIN
到之后的期间数据,然后汇总以获得总和。答案 1 :(得分:2)
使用distinct
显示here
代码:
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;
答案 2 :(得分:1)
在您的情况下,最简单的方法可能是分割位置:
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;
位置数量会增加胜利,损失和关系,因此将其除去会调整计数。