t-sql Совокупный Макс.

У меня есть таблица: CREATE TABLE [dbo].[test] ([name] nvarchar(max) NULL, [date] datetime NULL)

И записи на нем:

a 2010-09-02 12:00:00 
a 2010-09-02 11:00:00 
b 2010-09-02 12:00:00 
b 2010-09-02 11:00:00

И я хочу получить все имя с самой новой датой:

Я могу сделать:

select t.[name] from test t
group by t.[name]
having max(date) = (select MAX(DATE) from test where [name] = t.[name])

у которых есть одна проблема - я не могу назначить свидание

Я могу сделать:

select t.* 
    from test t
    where t.[date] = (select MAX(DATE) from test where [name] = t.[name])

который не имеет никаких проблем

Мой вопрос: Могу ли я сделать это лучше?? Я буду получать около 10 000 записей из таблицы приращения таблицы (каждый день еще 10 000 результатов).

С уважением


person dzajdol    schedule 02.09.2010    source источник


Ответы (2)


Какая версия SQL Server?

SQL 2005 и выше:

SELECT *
FROM
   (SELECT Item = Row_Number() OVER (PARTITION BY [name] ORDER BY [date] DESC), * FROM test) X
WHERE Item = 1

SQL 2000:

SELECT T.*
FROM
   test T
   INNER JOIN (
      SELECT [name], MaxDt = Max([date]) FROM test GROUP BY [name]
   ) X ON T.[name] = X.[name] AND T.[date] = X.MaxDt

Если у вас могут быть повторяющиеся даты, то для версии sql 2000 необходим еще один шаг, чтобы сократить ее до одной строки.

@Oded указал, что вы можете просто получить максимальную дату. Если все, что вам нужно, это имя и дата, то лучше всего подойдет его запрос. Но если мое подозрение верно, что вам нужно больше элементов из той же строки, то вам понадобятся такие запросы.

Вот еще одна версия SQL 2005:

SELECT
   T.*
FROM
   test T
   CROSS APPLY (
      SELECT TOP 1 [date]
      FROM test T2
      WHERE T.[name] = T2.[name]
      ORDER BY T2.[date] DESC
   ) X
WHERE
   T.[date] = X.[date]

Этот запрос будет иметь проблемы с повторяющимися максимальными датами для одного и того же имени.

Обновить

Теперь, когда я знаю, что это SQL 2008:

Решение row_number() самое простое и легкое. Я бы начал с этого. Если производительности недостаточно, а таблица является дочерней по отношению к родительской таблице, в которой каждое [имя] встречается только один раз, попробуйте решение CROSS APPLY с внешней таблицей (тест T) в качестве родителя:

SELECT
   X.*
FROM
   Parent P
   CROSS APPLY (
      SELECT TOP 1 *
      FROM test T
      WHERE P.[name] = T.[name]
      ORDER BY T.[date] DESC
   ) X

Если родительской таблицы нет, вы можете попробовать указанные выше запросы или использовать SELECT DISTINCT [name] FROM test, но я не уверен, что это улучшит производительность:

SELECT
   X.*
FROM
   (SELECT DISTINCT [name] FROM test) P
   CROSS APPLY (
      SELECT TOP 1 *
      FROM test T
      WHERE P.[name] = T.[name]
      ORDER BY T.[date] DESC
   ) X
person ErikE    schedule 02.09.2010
comment
я использовал sql 2008, и я хочу получить другие столбцы (не только имя и дату). Какие решения лучше?? может быть одна и та же дата для одного имени - person dzajdol; 02.09.2010
comment
Вам просто нужно попробовать их и посмотреть, что работает лучше всего. Кроме того, я исправил некоторые опечатки в своем обновлении, извините за это. - person ErikE; 02.09.2010

При этом будут выбраны разные имена и самая новая дата, связанная с каждым:

select t.[name], MAX(t.[date]) 
from test t
group by t.[name]

При использовании GROUP BY вы также можете использовать агрегатные функции в предложении SELECT для столбцов, не входящих в группу.

Из MSDN (агрегированные функции):

Агрегатные функции часто используются с предложением GROUP BY оператора SELECT.

person Oded    schedule 02.09.2010
comment
Это именно то, что я собирался опубликовать. Простое решение. - person codingbadger; 02.09.2010