优化体育网站排名查询

时间:2012-01-17 14:06:31

标签: sql-server sql-server-2005 tsql

我继承了一个跟踪曲棍球联赛比赛结果的应用程序。结果表如下所示:

[dbo].[league_division_games](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [division] [int] NULL,
    [team1] [int] NULL,
    [team1_score] [int] NULL,
    [team2] [int] NULL,
    [team2_score] [int] NULL,
    [shootout] [bit] NOT NULL)

现有的查询是一个令人讨厌的光标,表现非常糟糕。我甚至不会在这里发帖!

我开始重写这个,但它看起来很狡猾。

SELECT
    teams.id
    ,teams.name
    ,IsNull(COUNT(games.id), 0) AS GP
    ,SUM(CASE WHEN (teams.id = games.team1 AND games.team1_score > games.team2_score) OR (teams.id = games.team2 AND games.team2_score > games.team1_score) THEN 1 ELSE 0 END) AS W
    ,SUM(CASE WHEN (teams.id = games.team1 AND games.team1_score < games.team2_score) OR (teams.id = games.team2 AND games.team2_score < games.team1_score) THEN 1 ELSE 0 END) AS L
    ,SUM(CASE WHEN (teams.id = games.team1 AND games.team1_score = games.team2_score) OR (teams.id = games.team2 AND games.team1_score = games.team2_score) THEN 1 ELSE 0 END) AS T
FROM
    dbo.league_division_teams teams
    LEFT OUTER JOIN dbo.league_division_games games ON teams.id = games.team1 OR teams.id = games.team2
WHERE
    teams.division = @DIV
GROUP BY
    teams.id,
    teams.name

基本上我必须不断检查比分的每一方是否有胜负,失误,关系,进球和进球。

一点点的复杂性 - 在曲棍球比赛中,如果是加时赛失利,则输给失败者1分,胜利者2分。此外,如果是枪战,那么目标就等于两个分数中的最低分。

由于这些原因,聚合案例陈述将变得非常大,并且可能表现不佳。

我考虑过创建一个CTE来平缓一点,但还没有走下去。

有没有人以不同的方式接触过这种情况?我想这些统计数据非常普遍。

感谢。

1 个答案:

答案 0 :(得分:1)

另一种接近它的方法是分别聚合2个“边”并在最后组合它们。你必须稍微玩一下,看看它是否表现更好,但我在想这样的事情:

select
    id, name, sum(gp), sum(w), sum(l), sum(t)
from (
    SELECT
        teams.id
        ,teams.name
        ,IsNull(COUNT(games.id), 0) AS GP
        ,CASE WHEN team1_score > team2_score THEN 1 ELSE 0 END AS W
        ,CASE WHEN team1_score < team2_score THEN 1 ELSE 0 END AS L
        ,CASE WHEN team1_score = team2_score THEN 1 ELSE 0 END AS T
    FROM
        dbo.league_division_teams teams
        LEFT OUTER JOIN dbo.league_division_games games ON teams.id = games.team1 

    union

    SELECT
        teams.id
        ,teams.name
        ,IsNull(COUNT(games.id), 0) AS GP
        ,CASE WHEN team2_score > team1_score THEN 1 ELSE 0 END AS W
        ,CASE WHEN team2_score < team1_score THEN 1 ELSE 0 END AS L
        ,CASE WHEN team2_score = team1_score THEN 1 ELSE 0 END AS T
    FROM
        dbo.league_division_teams teams
        LEFT OUTER JOIN dbo.league_division_games games ON teams.id = games.team2
)
group by
    id, name