SQL需要自我加入和排名

时间:2012-06-16 11:12:40

标签: sql oracle

我有一张足球比赛表:

    CREATE TABLE matches(
    season NUMBER(4),
    matchDate DATE,
    homeTeam VARCHAR2(25),
    awayTeam VARCHAR2(25),
    homeGoals NUMBER(2),
    awayGoals NUMBER(2),
    totalGoals NUMBER(3));

对于每一行,我希望更新totalGoals列。 totalGoals的计算方法是在最近的5场比赛中将得分(homeGoals + awayGoals)的得分加在一起,其中homeTeam在主场比赛中得分最近的5场比赛得分匹配awayTeam播放的地方。

它计算仅使用同一赛季的比赛得分。它不包括当前行中的目标。如果任何一支球队在赛季中没有参加所需数量的比赛,totalGoals仍为空。

我可以使用PL / SQL更新它,但有没有办法只使用SQL?

2 个答案:

答案 0 :(得分:2)

如果我了解了您的需求,可以使用analytic functionswindowing clauses执行此操作。

select season, matchdate, hometeam, awayteam, homegoals, awaygoals,
    case when home_cnt >= 5 and away_cnt >= 5 then
        home_tot + away_tot
    else null end as totalgoals
from (
    select season, matchdate, hometeam, awayteam, homegoals, awaygoals,
        count(*) over (partition by season, hometeam
            order by matchdate
            rows between 5 preceding and 1 preceding) as home_cnt,
        sum(homegoals + awaygoals) over (partition by season, hometeam
            order by matchdate
            rows between 5 preceding and 1 preceding) as home_tot,
        count(*) over (partition by season, awayteam
            order by matchdate
            rows between 5 preceding and 1 preceding) as away_cnt,
        sum(homegoals + awaygoals) over (partition by season, awayteam
            order by matchdate
            rows between 5 preceding and 1 preceding) as away_tot
    from matches
)
order by season, matchdate, hometeam, awayteam;

内部选择使用countsum的分析版本以及窗口计算每个季节中每个主场/客场球队的比赛数量和比赛总数条款rows between ...限制前五个,不包括当前行,我认为这是你想要的。外部选择然后将相关总计一起添加到当前行中的两个团队,但检查两个计数并且如果其中任何一个是< 5.请注意,它只会访问matches表一次。

在订购前紧跟一个额外的过滤器:

where season = 2012 and homeTeam = 'Norwich' and awayteam = 'Aston Villa'

...你得到:

    SEASON MATCHDATE HOMETEAM                  AWAYTEAM                   HOMEGOALS  AWAYGOALS TOTALGOALS
---------- --------- ------------------------- ------------------------- ---------- ---------- ----------
      2012 13-MAY-12 Norwich                   Aston Villa                        2          0         30

您可以使用它来更新匹配行的表,但通常我会根据需要进行计算,以避免潜在的数据完整性错误,可能在视图中。

答案 1 :(得分:0)

我在MySQL上尝试了以下操作,但它失败了“错误代码:1093。您无法在FROM子句中为更新指定目标表'm'。”

也许您可以尝试使用Oracle。您必须使用Oracle限制行数的特定方式替换“limit 0,5”子句。我认为他们使用“rownum< 6”。

update matches m
  set totalGoals = (select sum(homeGoals) + sum(awayGoals) 
                      from matches
                      where homeTeam = m.homeTeam
                        and season = m.season
                        and matchDate < m.matchDate
                      having count(matchDate) > 4
                      order by matchDate limit 0,5) +
                   (select sum(homeGoals) + sum(awayGoals) 
                      from matches
                      where awayTeam = m.awayTeamm
                        and season = m.season
                        and matchDate < m.matchDate
                      having count(matchDate) > 4
                      order by matchDate limit 0,5);