SQL Server存储过程datetime参数选择数据

时间:2012-03-05 15:37:26

标签: sql-server datetime stored-procedures

我有一个足球联赛数据库,我正在努力获得特定日期球队的当前得分。如果我输入过去的日期,我希望在该特定日期得分 - 该日期各队的得分。

在我的数据库中,我有一个包含所有匹配项的表格,我有一个包含团队及其点数的表格(此表格实际上与当前分数相同)。

这两个表是:

 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作为参数来显示参数定义的该日期的当前得分(团队表)。

现在我正在选择比我想要的日期更大(更新)的所有比赛,并从球队点数中减去该比赛的结果。

但在我看来,做一些简单的事情需要做很多工作。

有没有人有更好的主意?

3 个答案:

答案 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占位符的原因。如果你愿意,你可以用实际的常量替换变量,或者你可以让查询参数化,以防你想要满足你的好奇心,看看如果一个不同的评分系统生效,团队的排名会是什么。