如何优化占用太多时间的查询

时间:2017-06-01 17:21:16

标签: sql sql-server sql-server-2008 sql-server-performance

在这个查询中,我在下面的查询中调用函数“fnGetPoolWinner”2-3次,       我认为这会降低其性能或多个案例陈述的原因。

时间大约是00:01:39。

我尝试过在表格中创建indx并创建Common Table Expression然后使用该查询等选项,但是没有找到任何解决方案来缩短它的时间。

DECLARE @TournamentId INT = 1

DECLARE @TournamentName AS NVARCHAR(MAX)

SELECT @TournamentName = TournamentName FROM Tournaments WHERE  TournamentId = @TournamentId


    SELECT 
    (SELECT CustomerIds FROM DBO.fnGetPoolWinner(SET_1.BracketBettingAmount,@TournamentId,
    (CASE
        WHEN SET_1.GAMES= 63
        THEN 1
        WHEN SET_1.GAMES= 31
        THEN 2
        WHEN SET_1.GAMES= 15
        THEN 3
        ELSE 0
    END))) AS [AccountNumber],
    @TournamentName AS TournamentName,
    (CASE
        WHEN SET_1.GAMES= 63
        THEN 'GENERAL POOL ROUND OF 64 $'+CAST(CAST(SET_1.BracketBettingAmount AS INT) AS NVARCHAR)+''
        WHEN SET_1.GAMES= 31
        THEN 'GENERAL POOL ROUND OF 32 $'+CAST(CAST(SET_1.BracketBettingAmount AS INT) AS NVARCHAR)+''
        WHEN SET_1.GAMES= 15
        THEN 'GENERAL POOL SWEET 16 $'+CAST(CAST(SET_1.BracketBettingAmount AS INT) AS NVARCHAR)+''
        ELSE ''
    END) AS [PoolName],
    (SELECT BracketNames FROM DBO.fnGetPoolWinner(SET_1.BracketBettingAmount,@TournamentId,
    (CASE
        WHEN SET_1.GAMES= 63
        THEN 1
        WHEN SET_1.GAMES= 31
        THEN 2
        WHEN SET_1.GAMES= 15
        THEN 3
        ELSE 0
    END))) AS GroupEntries,
    'Public' AS Access,
    COUNT(SET_1.BracketId) AS Members, 
    COUNT(SET_1.BracketId)*SET_1.BracketBettingAmount AS CurrentPoolPrize, 
    (SELECT WinnerNames FROM DBO.fnGetPoolWinner(SET_1.BracketBettingAmount,@TournamentId,
    (CASE
        WHEN SET_1.GAMES= 63
        THEN 1
        WHEN SET_1.GAMES= 31
        THEN 2
        WHEN SET_1.GAMES= 15
        THEN 3
        ELSE 0
    END))) AS WinnersName,
    (CASE
        WHEN SET_1.GAMES= 63
        THEN 1
        WHEN SET_1.GAMES= 31
        THEN 2
        WHEN SET_1.GAMES= 15
        THEN 3
        ELSE 0
    END) AS RoundId,
    SET_1.BracketBettingAmount AS BettingAmount
    FROM
        (SELECT BR.BracketId,
            BracketBettingAmount,
            (SELECT COUNT(1) FROM BracketPredictions AS BP WHERE BP.BracketPredictionBracketId =BR.BracketId) AS GAMES
        FROM Brackets AS BR WHERE BR.BracketTournamentId = @TournamentId AND BR.IsDeleted = 0) SET_1 WHERE SET_1.GAMES > 0
    GROUP BY SET_1.BracketBettingAmount, SET_1.GAMES HAVING SET_1.BracketBettingAmount IN (1,5,10,25)

2 个答案:

答案 0 :(得分:0)

试试这个,未经过测试

DECLARE @TournamentId INT = 1

    with SET_1 as (

      SELECT BR.BracketId, BracketBettingAmount as BettingAmount, W.GAMES, TN.TournamentName,
             case W.GAMES 
             WHEN 63 THEN 1
             WHEN 31 THEN 2
             WHEN 15 THEN 3
             ELSE 0 END as IDGAME,

             CASE W.GAMES
             WHEN 63 THEN 'GENERAL POOL ROUND OF 64 $'+CAST(CAST(BracketBettingAmount AS INT) AS NVARCHAR)
             WHEN 31 THEN 'GENERAL POOL ROUND OF 32 $'+CAST(CAST(BracketBettingAmount AS INT) AS NVARCHAR)
             WHEN 15 THEN 'GENERAL POOL SWEET 16 $'   +CAST(CAST(BracketBettingAmount AS INT) AS NVARCHAR)
             ELSE '' END AS PoolName,

             TN.TournamentId

             FROM Brackets AS BR 
             cross apply
             (
                SELECT COUNT(*) GAMES FROM BracketPredictions AS BP WHERE BP.BracketPredictionBracketId =BR.BracketId
             ) W

             inner join Tournaments TN on BR.BracketTournamentId=TN.TournamentId

             WHERE BR.IsDeleted = 0 and BracketBettingAmount IN (1,5,10,25) and W.GAMES>0 and TN.TournamentId = @TournamentId


    ),

    NbBracketId as ( select NbBracketId, count(*) Nb from SET_1 group by NbBracketId) 


    SELECT 
    Y.CustomerIds AccountNumber, X.TournamentName, X.PoolName, Y.BracketNames AS GroupEntries, 'Public' AS Access,
    Z.NB AS Members, Z.NB*X.BettingAmount AS CurrentPoolPrize, Y.WinnerNames, X.IDGAME AS RoundId, X.BettingAmount
    FROM SET_1 X 
    outer apply DBO.fnGetPoolWinner(SET_1.BracketBettingAmount, SET_1.TournamentId, SET_1.IDGAME) as Y
    inner join NbBracketId Z on X.BracketId=Z.BracketId

答案 1 :(得分:0)

DBO.fnGetPoolWinner可以自行调整大小。

尝试这种方法,

DECLARE @TournamentId INT = 1
DECLARE @TournamentName AS NVARCHAR(MAX)
SELECT @TournamentName = TournamentName FROM Tournaments WHERE  TournamentId = @TournamentId
select @TournamentName TournamentName,
CustomerIds AS [AccountNumber]
,(CASE
        WHEN SET_1.GAMES= 63
        THEN 'GENERAL POOL ROUND OF 64 $'+CAST(CAST(SET_1.BracketBettingAmount AS INT) AS NVARCHAR)+''
        WHEN SET_1.GAMES= 31
        THEN 'GENERAL POOL ROUND OF 32 $'+CAST(CAST(SET_1.BracketBettingAmount AS INT) AS NVARCHAR)+''
        WHEN SET_1.GAMES= 15
        THEN 'GENERAL POOL SWEET 16 $'+CAST(CAST(SET_1.BracketBettingAmount AS INT) AS NVARCHAR)+''
        ELSE ''
    END) AS [PoolName]
    ,ca.BracketNames as GroupEntries
     'Public' AS Access,
    COUNT(SET_1.BracketId) AS Members, 
    COUNT(SET_1.BracketId)*SET_1.BracketBettingAmount AS CurrentPoolPrize
    ,WinnerNames  as WinnersName
    , (CASE
        WHEN SET_1.GAMES= 63
        THEN 1
        WHEN SET_1.GAMES= 31
        THEN 2
        WHEN SET_1.GAMES= 15
        THEN 3
        ELSE 0
    END) AS RoundId,
    SET_1.BracketBettingAmount AS BettingAmount
 FROM
       (SELECT BR.BracketId,
            BracketBettingAmount,
            (SELECT COUNT(1) FROM BracketPredictions AS BP WHERE BP.BracketPredictionBracketId =BR.BracketId) AS GAMES
        FROM Brackets AS BR WHERE BR.BracketTournamentId = @TournamentId AND BR.IsDeleted = 0) SET_1 
        WHERE SET_1.GAMES > 0
    GROUP BY SET_1.BracketBettingAmount, SET_1.GAMES 
    HAVING SET_1.BracketBettingAmount IN (1,5,10,25)

    cross apply(SELECT CustomerIds,BracketNames,WinnerNames
     FROM DBO.fnGetPoolWinner(SET_1.BracketBettingAmount,@TournamentId,
    (CASE
        WHEN SET_1.GAMES= 63
        THEN 1
        WHEN SET_1.GAMES= 31
        THEN 2
        WHEN SET_1.GAMES= 15
        THEN 3
        ELSE 0
    END)) )ca