【问题标题】:Select record if value larger than previous in SQL如果值大于 SQL 中的先前值,则选择记录
【发布时间】:2018-05-16 04:10:26
【问题描述】:

我有这个 T-SQL 查询

WITH CTE AS 
(
    SELECT  
        m.Season AS 'Season',
        SUM(bi.Runs) AS 'Runs',
        p.LastName + ' ' + SUBSTRING(p.FirstName, 1, 1) AS 'PlayerName' 
    FROM Player p
    JOIN BatInnings bi on bi.fk_Player_Id = p.id  
    JOIN Innings i on i.Id = bi.fk_Innings_Id
    JOIN Team t on t.id = i.fk_Team_Id
    JOIN Match m on m.id = i.fk_Match_Id
    WHERE   
        (p.id = @playerId OR @playerId IS NULL) 
        AND m.MatchType IN (@matchType1, @matchType2, @matchType3) 
        AND (i.fk_Team_Id = @teamId OR @teamId IS NULL) 
        AND (t.fk_Club_Id = @clubId OR @clubId IS NULL)
    GROUP BY 
        m.season, p.LastName + ' ' + SUBSTRING(p.FirstName, 1, 1)
) 
SELECT CTE.* 
FROM CTE 
WHERE CTE.Runs = (SELECT MAX(CTE2.Runs) 
                  FROM CTE CTE2 
                  WHERE CTE2.Season = CTE.Season) 
ORDER BY CTE.Season

这会根据每个赛季的最高得分手拉出一个列表。结果将如下所示。

Season   Runs   Player
1990/91  689    Todd D
1991/92  617    Grantham N
1992/93  838    Todd D
1993/94  532    Todd D
1994/95  628    Todd D
1995/96  584    Downer M
1996/97  743    Todd D
1997/98  742    Brown S
1998/99  841    Todd D
1999/00  902    Hart M

我想进一步查询这个查询,然后找出每条记录高于前一个选择的记录。因此,使用前面的列表,此查询的结果将类似于

Season   Runs   Player
1990/91  689    Todd D
1992/93  838    Todd D
1998/99  841    Todd D
1999/00  902    Hart M

如果需要,很乐意提供更多信息。

谢谢

【问题讨论】:

    标签: sql sql-server common-table-expression sql-server-2017


    【解决方案1】:

    试试这个:

    ;with cte
    AS
    (
     SELECT '1990/91' AS Season, 689 AS Runs, 'Todd D' AS Player
      Union All
     SELECT '1991/92' AS Season, 617 AS Runs, 'Grantham N' AS Player
      Union All
     SELECT '1992/93' AS Season, 838 AS Runs, 'Todd D' AS Player
      Union All
     SELECT '1993/94' AS Season, 532 AS Runs, 'Todd D' AS Player
      Union All
     SELECT '1994/95' AS Season, 628 AS Runs, 'Todd D' AS Player
      Union All
     SELECT '1995/96' AS Season, 584 AS Runs, 'Downer M' AS Player
      Union All
     SELECT '1996/97' AS Season, 743 AS Runs, 'Todd D' AS Player
     Union All
     SELECT '1997/98' AS Season, 742 AS Runs, 'Brown S' AS Player
      Union All
     SELECT '1998/99' AS Season, 841 AS Runs, 'Todd D' AS Player
     Union All
    SELECT '1999/00' AS Season, 902 AS Runs, 'Hart M' AS Player
     )
    
    ,cte2
    AS
    (
      SELECT *,
      MAX(Runs) OVER(Order By (Select NULL) ROWS BETWEEN UNBOUNDED PRECEDING AND 
      CURRENT ROW) As PreMax
      FROM cte
    )
    
     Select Season,Runs,Player from Cte2
     Where Runs>=PreMax
    

    SQL 小提琴:http://sqlfiddle.com/#!18/c6e8e/9

    【讨论】:

    【解决方案2】:

    您可以使用窗口函数MAX() OVER () 来获得该赛季之前的最大运行次数以进行比较:

    WITH CTE AS (
        SELECT  m.Season AS 'Season',
            SUM(bi.Runs) AS 'Runs',
            p.LastName + ' ' + SUBSTRING(p.FirstName, 1, 1) AS 'PlayerName' 
        FROM Player p
        JOIN BatInnings bi on bi.fk_Player_Id = p.id  
        JOIN Innings i on i.Id = bi.fk_Innings_Id
        JOIN Team t on t.id = i.fk_Team_Id
        JOIN Match m on m.id = i.fk_Match_Id
        WHERE (p.id = @playerId OR @playerId IS NULL) 
            AND m.MatchType IN (@matchType1, @matchType2, @matchType3) 
            AND (i.fk_Team_Id = @teamId OR @teamId IS NULL) 
            AND (t.fk_Club_Id = @clubId OR @clubId IS NULL)
        GROUP BY m.season, p.LastName + ' ' + SUBSTRING(p.FirstName, 1, 1)
    ) 
    , cte1 AS 
    (
        SELECT *
        FROM CTE c
        WHERE Runs = (
            SELECT MAX(Runs) 
            FROM CTE 
            WHERE Season = c.Season
        ) 
    )
    , cte2 AS 
    (
        SELECT season, COALESCE(MAX(runs) OVER (ORDER BY season), 0) AS max_runs_to_season
        FROM cte1 
    )
    SELECT *
    FROM cte1 c
    WHERE runs >= (
        SELECT max_runs_to_season
        FROM cte2 
        WHERE season = c.season
    )
    ORDER BY season;
    

    【讨论】:

      【解决方案3】:

      我对 SQL 中的窗口函数不太熟悉,所以我的回答只使用 CTE 和子查询。

      我将您的主要查询放在一个名为 [SeasonResults] 的新 CTE 中,并从那里扩展了查询。

      一个名为 [MaxSeasonResults] 的新 CTE 决定了每个赛季的最佳结果。

      WITH
          [CTE] AS
          (
              SELECT  
                  m.Season AS 'Season',
                  SUM(bi.Runs) AS 'Runs',
                  p.LastName + ' ' + SUBSTRING(p.FirstName, 1, 1) AS 'PlayerName' 
              FROM Player p
              JOIN BatInnings bi on bi.fk_Player_Id = p.id  
              JOIN Innings i on i.Id = bi.fk_Innings_Id
              JOIN Team t on t.id = i.fk_Team_Id
              JOIN Match m on m.id = i.fk_Match_Id
              WHERE   
                  (p.id = @playerId OR @playerId IS NULL) 
                  AND m.MatchType IN (@matchType1, @matchType2, @matchType3) 
                  AND (i.fk_Team_Id = @teamId OR @teamId IS NULL) 
                  AND (t.fk_Club_Id = @clubId OR @clubId IS NULL)
              GROUP BY 
                  m.season, p.LastName + ' ' + SUBSTRING(p.FirstName, 1, 1)
          ),
          [SeasonResults] AS
          (
              SELECT CTE.* 
              FROM CTE 
              WHERE CTE.Runs = (SELECT MAX(CTE2.Runs) 
                                FROM CTE CTE2 
                                WHERE CTE2.Season = CTE.Season) 
              ORDER BY CTE.Season
          ),
          [MaxSeasonResults] AS
          (
              SELECT
                  [Season],
                  [MaxRuns] = MAX([Runs])
              FROM [SeasonResults]
              GROUP BY [Season]
          )
      SELECT R.*
      FROM
          [SeasonResults] AS R
          JOIN [MaxSeasonResults] AS M ON
              M.[Season] = R.[Season]
              AND M.[MaxRuns] = R.[Runs]
      WHERE
          M.[MaxRuns] > (SELECT COALESCE(MAX(_M.[MaxRuns]), 0)
                         FROM [MaxSeasonResults] AS _M
                         WHERE _M.[Season] < M.[Season])
      ORDER BY R.[Season];
      

      也许可以进行更多优化/重构,但我必须使用包含给定结果集的临时表来测试我的查询,因此我很难检查和测试任何进一步的优化。对此感到抱歉。

      【讨论】:

        猜你喜欢
        • 2020-01-31
        • 2020-09-01
        • 2020-02-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-14
        • 2017-03-06
        • 1970-01-01
        相关资源
        最近更新 更多