我有一个足球联赛数据库,我正在努力获得特定日期球队的当前得分。如果我输入过去的日期,我希望在该特定日期得分 - 该日期各队的得分。
在我的数据库中,我有一个包含所有匹配项的表格,我有一个包含团队及其点数的表格(此表格实际上与当前分数相同)。
这两个表是:
create table teams
(
id char(3) primary key,
name varchar(40),
nomatches int,
owngoals int,
othergoals int,
points int
)
create table matches
(
id int identity(1,1),
homeid char(3) foreign key references teams(id),
outid char(3) foreign key references teams(id),
homegoal int,
outgoal int,
matchdate datetime
)
我正在尝试使用存储过程,其中我有datetime
作为参数来显示参数定义的该日期的当前得分(团队表)。
现在我正在选择比我想要的日期更大(更新)的所有比赛,并从球队点数中减去该比赛的结果。
但在我看来,做一些简单的事情需要做很多工作。
有没有人有更好的主意?
答案 0 :(得分:0)
你为什么减去?在我看来,正确的方法是采取联赛开始日期并计算从那天到选定日期的分数。
答案 1 :(得分:0)
我不确定你为什么要把这么简单的查询放到一个程序中,但基本上你要问的是如下:
CREATE PROCEDURE sp_goals_to_date(@todate DATETIME) AS
SELECT id, SUM(homegoal) AS homegoal, SUM(outgoal) AS outgoal FROM matches WHERE matchdate <= @mydate
Fedor所说的是正确的 - 从一开始就进行单一计算比从两个不同的表中进行计算更有效。
答案 2 :(得分:0)
我首先会像这样转换matches
表:
SELECT
teamid = CASE t.calchometeam WHEN 1 THEN m.homeid ELSE m.outid END,
owngoal = CASE t.calchometeam WHEN 1 THEN m.homegoal ELSE m.outgoal END,
othergoal = CASE t.calchometeam WHEN 0 THEN m.homegoal ELSE m.outgoal END,
points = CASE m.homegoal
WHEN m.outgoal THEN @drawpoints
ELSE (SIGN(m.homegoal - m.outgoal) + 1) / 2 ^ ~m.playedhome) * @winpoints
+ (SIGN(m.homegoal - m.outgoal) + 1) / 2 ^ m.playedhome) * @losspoints
END
FROM matches m
CROSS JOIN (
SELECT CAST(0 AS bit) UNION ALL
SELECT CAST(1 AS bit)
) AS t (calchometeam)
WHERE m.matchdate <= @givendate
现在计算必要的总数更容易:
SELECT
teamid,
nomatches = COUNT(*),
owngoals = SUM(owngoal),
othergoals = SUM(othergoal),
points = SUM(points)
FROM transformed_matches
GROUP BY
teamid
下一步是将最后一个结果集加入teams
表以获取团队名称。如果你真的需要最后一步,你当然可以按照你想要的方式从头开始计算,即只计算你需要从当前值中减去的统计数,而不是实际的排名。因此,使用此反向逻辑,整个查询可能如下所示:
WITH
transformed_matches AS (
SELECT
matchid = m.id,
teamid = CASE t.calchometeam WHEN 1 THEN m.homeid ELSE m.outid END,
owngoal = CASE t.calchometeam WHEN 1 THEN m.homegoal ELSE m.outgoal END,
othergoal = CASE t.calchometeam WHEN 0 THEN m.homegoal ELSE m.outgoal END,
points = CASE m.homegoal
WHEN m.outgoal THEN @drawpoints
ELSE (SIGN(m.homegoal - m.outgoal) + 1) / 2 ^ ~m.playedhome) * @winpoints
+ (SIGN(m.homegoal - m.outgoal) + 1) / 2 ^ m.playedhome) * @losspoints
END
FROM matches m
CROSS JOIN (
SELECT CAST(0 AS bit) UNION ALL
SELECT CAST(1 AS bit)
) AS t (calchometeam)
WHERE m.matchdate > @givendate
),
aggregated AS (
SELECT
teamid,
nomatches = COUNT(*),
owngoals = SUM(owngoal),
othergoals = SUM(othergoal),
points = SUM(points)
FROM transformed_matches
GROUP BY
teamid
)
SELECT
t.id,
t.name,
nomatches = t.nomatches - ISNULL(a.nomatches , 0),
owngoals = t.owngoals - ISNULL(a.orngoals , 0),
othergoals = t.nomatches - ISNULL(a.othergoals, 0),
points = t.points - ISNULL(a.points , 0)
FROM teams t
LEFT JOIN aggregated a ON t.id = a.teamid
注意:你没有说明你想要哪种足球,但是生活在欧洲,我更容易接受足球联赛而不是任何其他种类。然而,因为我不确定,我决定参数化我的查询。这就是为什么您可以看到所有@winpoints
,@drawpoints
和@losspoints
占位符的原因。如果你愿意,你可以用实际的常量替换变量,或者你可以让查询参数化,以防你想要满足你的好奇心,看看如果一个不同的评分系统生效,团队的排名会是什么。