Выберите запись, если значение больше, чем предыдущее в SQL - PullRequest
0 голосов
/ 16 мая 2018

У меня есть этот запрос 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

Рад предоставить больше информации, если требуется.

Спасибо

Ответы [ 3 ]

0 голосов
/ 16 мая 2018

Попробуйте это:

;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 Fiddle: http://sqlfiddle.com/#!18/c6e8e/9

0 голосов
/ 16 мая 2018

Я не очень знаком с оконными функциями в SQL, поэтому в моем ответе используются только CTE и подзапросы.

Я поместил ваш основной запрос в новый CTE с именем [SeasonResults] и расширил его оттуда.

Новый CTE с именем [MaxSeasonResults] определяет лучший результат за сезон.

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];

Возможно, возможны дополнительные оптимизации / рефакторинги, но мне пришлось проверить свой запрос, используя временную таблицу, содержащую вашуданный набор результатов, поэтому мне было довольно сложно проверить и протестировать дальнейшую оптимизацию.Извините за это.

0 голосов
/ 16 мая 2018

Вы можете использовать оконную функцию 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;
...