改进SQL存储过程以成对执行过程

时间:2014-06-02 05:42:25

标签: sql-server performance tsql stored-procedures

更新: 我将第一部分改写为基于setbased的方法:

declare @AllRunnersString nvarchar(200) ='2342;1228;1075;266;423;2849;1690;488;162;1153;1666'
DECLARE @pairs table
(p1 int,p2 int) 
insert into @pairs(p1, p2)
select sp1.value as p1, sp2.value as p2
from dbo.split(';', @AllRunnersString) sp1
inner join dbo.split(';', @AllRunnersString) sp2
on sp1.value <> sp2.value

这会生成对。

Head2Head获取id并返回一个包含所有具有两个id的事件的表。     @rtn表(     eventid int,     p1 int,     p2 int,     ldiff float,     pdiff float,     胜利者     )

我需要接受所有这些事件,并将它们存储在表格中,用于@pairs的所有组合。

使用基于过程的方法,我会在@pairs上运行游标,并使用过程计算每对的值并插入到最终表中。

也许这部分有一种基于设定的方法..

3 个答案:

答案 0 :(得分:0)

您的描述很容易理解,如果您的功能 getHead2Head 的文字也可用,那么仍然很好。还提供一些数据来证明你的问题。

我读到了你的解释,我有一些建议

  1. 为什么你使用2循环,而不是制作一个循环。

  2. 在这种情况下,您可以更好地控制使用光标,而不是在适当时使用光标,最后不需要设置更新以进行重置。

  3. 快速查询的主要问题是与每个查询以及每个条件相关的问题。

    您可以为临时表提供主键,这样可以获得快速结果。(创建主表像普通表一样简单)

    Creating a Primary Key on a temp table - When?

答案 1 :(得分:0)

最好切换到使用表值参数或XML传递参数,这自然支持多个值而不是将它们塞进字符串中,但是因为你已经有了这个部分而且它是& #34;工作&#34;对你而言,我们不管它。

以下内容应相同:

declare @AllRunnersString nvarchar(200)   
    ='2342;1228;1075;266;423;2849;1690;488;162;1153;1666'

declare @rtn table
(
   eventid int,
   player1 int,
   player2 int,
   lengthdiff float,
   placediff float,
   winner int
)

declare @playerids table
(
    playerid int
)

-- parse string into table
insert into @playerids(playerid)
   select value 
   from split(';', @AllRunnersString) 

insert into @rtn(eventid, player1, player2, lengthdiff, placediff, winner)
select eventid, player1, player2, lengthdiff, placediff, winner 
from
 @playerids p1
   inner join
 @playerids p2
   on
     p1.playerid != p2.playerid
   cross apply
    getHead2Head(p1.playerid, p2.playerid, 3)

如果我们可以取消对getHead2Head的调用并将其内容直接包含在此查询中,则可能还有其他机会可以改进这一点。

答案 2 :(得分:0)

您需要重建一个真正的数据库任务 - 构建循环以匹配记录 - 在TSQL中。不要使用过程代码,使用set代码,让服务器执行循环和填充。他会做得更好,没有进攻。例如,如果您想随意加入只有一个合作伙伴/候选人对的合作伙伴,您可以执行以下操作:

WITH player_combination
AS (
    --Cross Joins selects all combinations of mutually different players
    SELECT p.playerid [partner], c.playerid candidate,newid() random_id
    FROM @playerid p, @playerid c
    WHERE p.playerid<>c.playerid
)
SELECT pc.[partner],pc.candidate
FROM player_combination pc
    JOIN (SELECT [partner], max(random_id) random_id --Select the record with max random_id
            FROM player_combination
            GROUP BY [partner]) tmp ON tmp.[partner]=pc.[partner] AND tmp.random_id=pc.random_id

如果您可以选择免费播放器的最大ID,则声明更容易:

WITH player_combination
AS (
    --Cross Joins selects all combinations of mutually different players
    SELECT p.playerid [partner], c.playerid candidate
    FROM @playerid p, @playerid c
    WHERE p.playerid<>c.playerid
)
SELECT pc.[partner],pc.candidate
FROM player_combination pc
    JOIN (SELECT [partner], max(candidate) candidate --Select the record with max candidate id
            FROM player_combination
            GROUP BY [partner]) tmp ON tmp.[partner]=pc.[partner] AND tmp.random_id=pc.random_id

我很确定你也可以摆脱getHead2Head功能。