[英]SQL Server stored procedure datetime parameter on selecting data
I have a football league database and I am trying to get the current score of the teams on a specific date. 我有一个足球联赛数据库,我正在尝试获取特定日期球队的当前得分。 If I type in a date in the past I want the score at that specific date - the points of each teams on that date.
如果我输入过去的日期,我希望获得该特定日期的分数-每个团队在该日期的分数。
In my database I have a table that includes all the matches and I have a table with the teams and their point (this table is actually the same as the current score). 在我的数据库中,我有一个包含所有比赛的表格,并且我有一个包含球队及其得分的表格(该表格实际上与当前得分相同)。
The two tables are: 这两个表是:
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
)
I am trying to use a stored procedure where I have a datetime
as a parameter to show the current score (the team table) at that date defined by the parameter. 我正在尝试使用一个存储过程,其中有一个
datetime
作为参数,以显示该参数定义的那个日期的当前得分(团队表)。
Right now I'm selecting all the matches that is bigger (newer) than the date I want til score table from and subtracting the result of that match from the teams point. 现在,我要选择所有比(直到)我想要直到截止得分表的日期更大(更新)的比赛,并从球队得分中减去该比赛的结果。
But it seems to me that it is a lot of work to do for something that simple. 但是在我看来,要做这么简单的事情需要做很多工作。
Does anyone have a better idea? 有谁有更好的主意吗?
Why do you subtract? 为什么要减去? Seems to me that the correct way to go would be to take the league start date and calculate the scores from that day up to selected date.
在我看来,正确的做法是取得联赛开始日期并计算从当天到选定日期的得分。
I'm not sure why you would want to put such a simple query into a procedure, but essentially what you're asking is as follows: 我不确定为什么要在过程中放入这样一个简单的查询,但是实际上您要问的是以下内容:
CREATE PROCEDURE sp_goals_to_date(@todate DATETIME) AS
SELECT id, SUM(homegoal) AS homegoal, SUM(outgoal) AS outgoal FROM matches WHERE matchdate <= @mydate
What Fedor says is correct - it is more efficient to do a single calculation from the beginning of time, than to have to do a calc from two different tables. Fedor所说的是正确的-从开始就进行一次计算比从两个不同的表进行计算要有效。
I would first transform the matches
table like this: 我首先要像这样转换
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
Now it's easier to calculate the necessary totals: 现在,更容易计算所需的总数:
SELECT
teamid,
nomatches = COUNT(*),
owngoals = SUM(owngoal),
othergoals = SUM(othergoal),
points = SUM(points)
FROM transformed_matches
GROUP BY
teamid
Next step would be to join the last result set to the teams
table to get the team's names. 下一步是将最后一个结果集加入到
teams
表中,以获取团队的名称。 And if you actually need that final step, you could, of course, perform the calculations the way you intended from the beginning, ie calculate only the stats you need to subtract from the current values, rather than the actual standings. 而且,如果您实际上需要最后一步,那么您当然可以从一开始就按照预期的方式执行计算,即仅计算需要从当前值中减去的统计信息,而不是实际的排名。 So, using this inverted logic, the entire query might look like this:
因此,使用此反向逻辑,整个查询可能如下所示:
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
Note: You didn't specify which kind of football you meant, but living in Europe, it was easier for me to assume association football rather than any other kind. 注意:您没有指定足球的意思,但是住在欧洲,对我来说,参加协会橄榄球比其他任何一种都容易。 Yet, because I was not sure, I decided to parametrise my query.
但是,由于不确定,我决定对查询进行参数化。 That is why you can see all those
@winpoints
, @drawpoints
and @losspoints
placeholders. 这就是为什么您可以看到所有这些
@winpoints
, @drawpoints
和@losspoints
占位符的原因。 You can replace the variables with the actual constants, if you like, or you could leave the query parametrised in case you wanted to satisfy your curiosity as to what the team's standings would have been if a different scoring system were in effect. 如果愿意,可以将变量替换为实际的常数,也可以保留参数化的查询,以防您好奇,如果采用不同的评分系统,团队的地位将是什么样。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.