2010-06-01 2 views
1

Я работаю с 12.5 сервером Sybase и у меня есть таблица определяется как таковую:Есть ли способ найти записи TOP X сгруппированными данными?

CREATE TABLE SomeTable(
    [GroupID] [int] NOT NULL, 
    [DateStamp] [datetime] NOT NULL, 
    [SomeName] varchar(100), 
    PRIMARY KEY CLUSTERED (GroupID,DateStamp) 
) 

Я хочу, чтобы иметь возможность перечислить, в [GroupID], только последние X записи по [DATESTAMP]. Кикер X> 1, поэтому простой старый MAX() не будет его обрезать. Я предполагаю, что есть замечательно неприятный способ сделать это с помощью курсоров и что-нет, но мне интересно, есть ли более простой способ без этого.

Я знаю, что я что-то не хватает совершенно очевидно, и я буду пинать себя за не получить его, но .... я не получаю его. Пожалуйста помоги.

Есть ли способ, чтобы найти TOP X записей, но с сгруппированными данными?

ответ

3

Согласно онлайн-руководству Sybase 12.5 поддерживает функции WINDOW и ROW_NUMBER(), хотя их синтаксис немного отличается от стандартного SQL.

попробовать что-то вроде этого:

SELECT SP.* 
FROM (
    SELECT *, ROW_NUMBER() OVER (windowA ORDER BY [DateStamp] DESC) AS RowNum 
    FROM SomeTable 
    WINDOW windowA AS (PARTITION BY [GroupID]) 
) AS SP 
WHERE SP.RowNum <= 3 
ORDER BY RowNum DESC; 

У меня нет экземпляра Sybase, поэтому я не проверял это. Я просто синтезирую этот пример из документа.


Я допустил ошибку. Документ, на который я смотрел, был Sybase SQL Anywhere 11. Кажется, что Sybase ASA не поддерживает предложение WINDOW вообще, даже в самой последней версии.

Вот еще один запрос, который мог бы сделать то же самое. Вы можете использовать самосоединение для соответствия каждой строке SomeTable ко всем строкам с тем же самым идентификатором GroupID и более поздним DateStamp. Если есть три или меньше строк, то у нас есть одна из трех лучших.

SELECT s1.[GroupID], s1.[Foo], s1.[Bar], s1.[Baz] 
FROM SomeTable s1 
LEFT OUTER JOIN SomeTable s2 
    ON s1.[GroupID] = s2.[GroupID] AND s1.[DateStamp] < s2.[DateStamp] 
GROUP BY s1.[GroupID], s1.[Foo], s1.[Bar], s1.[Baz] 
HAVING COUNT(*) < 3 
ORDER BY s1.[DateStamp] DESC; 

Обратите внимание, что вы должны список те же столбцы в SELECT списке, как вы перечислите в пункте GROUP BY. В принципе, все столбцы от s1, которые вы хотите, чтобы этот запрос возвращался.

+0

Если это работает, кажется, что это лучше всего с момента его единственного запроса. – Justin

+0

Большое спасибо. Я попробую это, когда я получу работу в пятницу и посмотрю, работает ли это. –

+0

Это, похоже, не работает: «Неверный синтаксис рядом с ключевым словом« OVER ».» Я все равно буду пытаться. –

1

Вот довольно неприступный путь!

SELECT GroupID, DateStamp, SomeName 
FROM SomeTable ST1 
WHERE X < 
    (SELECT COUNT(*) 
    FROM SomeTable ST2 
    WHERE ST1.GroupID=ST2.GroupID AND ST2.DateStamp > ST1.DateStamp) 

Редактировать решение Билла намного предпочтительнее, хотя.