Найти все оценки за 2-ю до самой последней даты - PullRequest
3 голосов
/ 14 июня 2011

У меня есть таблица истории, которая содержит оценку по группе на дату (PK - группа, дата). Какой SQL-запрос может получить оценки для всех групп за 2-ю последнюю дату?

ETA: даты одинаковы для разных групп (каждая оценка заносится в таблицу истории одновременно для каждой группы).

Ответы [ 4 ]

4 голосов
/ 14 июня 2011
select *
from ScoreHistory sc1
where exists
(
    select GroupId, max(ScoreDate) RecentScoreDate
    from ScoreHistory sc2
    where not exists
    (
        select GroupId, max(ScoreDate) RecentScoreDate
        from ScoreHistory sc3
        group by GroupId
        having GroupId = sc2.GroupId and max(ScoreDate) = sc2.ScoreDate
    )
    group by GroupId
    having GroupId = sc1.GroupId and max(ScoreDate) = sc1.ScoreDate
)

Установка:

create table ScoreHistory(GroupId int, ScoreDate datetime)

insert ScoreHistory
    select 1, '2011-06-14' union all
    select 1, '2011-06-15' union all
    select 1, '2011-06-16' union all
    select 2, '2011-06-15' union all
    select 2, '2011-06-16' union all
    select 2, '2011-06-17' 

Запрос будет выглядеть так же просто, как показано ниже для MS SQL 2005 +

;with cte
as
(
    select *, row_number() over(partition by GroupId order by ScoreDate desc) RowNumber
    from ScoreHistory
)
select *
from cte
where RowNumber = 2
3 голосов
/ 14 июня 2011

Вам нужно два агрегата

  1. получить максимальное количество дат для группы
  2. получить максимальные даты для группы, которые меньше, чем даты с шага 1
  3. присоединиться к счету из этого агрегата

Что-то вроде

SELECT
    Group, Date, Score
FROM
    ( ..2nd max date per group
    SELECT
       Group, MAX(Date) AS TakeMe
    FROM
        ( --max date per group
        SELECT
           Group, MAX(Date) AS IgnoreMe
        FROM
           MyTable
        GROUP BY
           Group
        ) ex
        JOIN
        MyTable M ON ex.Group = M.Group AND ex.IgnoreMe > M.Date
    GROUP BY
        M.Group
    ) inc
    JOIN
    MyTable M2 ON inc.Group = M2.Group AND inc.TakeMe = M2.Date

Это , поэтому намного проще в SQL Server 2005 с ROW_NUMBER () ...

2 голосов
/ 14 июня 2011
SELECT *
FROM tblScore
WHERE EXISTS
(
    SELECT NULL
    FROM tblScore as tblOuter
    WHERE NOT EXISTS
    (
        SELECT NULL
        FROM tblScore As tblInner
        WHERE tblInner.[group] = tblOuter.[group]
        GROUP BY [group]
        HAVING MAX(tblInner.[date]) = tblOuter.[date]
    ) 
    AND tblOuter.[group] = tblScore.[group]
    GROUP BY [group]
    HAVING MAX(tblOuter.[date]) = tblScore.[date]
)
2 голосов
/ 14 июня 2011

Попробуй это. Я пытаюсь сначала получить TOP 2 DISTINCT Dates Desc, который будет работать, если вы используете только даты, а не datetime. Затем перевернуть эту таблицу и получить TOP 1 и использовать этот результат как 2-ую самую последнюю дату, чтобы получить оценки групп.

SELECT *
FROM YourTable
INNER JOIN 
(SELECT TOP 1 x.[date]
FROM
    (SELECT TOP 2 DISTINCT [date]
    FROM YourTable
    ORDER BY [date] DESC) AS x
ORDER BY [date] ASC) AS y
ON y.[date] = YourTable.[date]

Я думаю, что это может понадобиться WHERE y.date = YourTable.date, но я не уверен

...