2014-02-10 6 views
1

У меня есть таблица со следующими:Выберите X новые строки для каждого уникального значения столбца

  • EVENTID -> первичный ключ, более высокие цифры означают более новый
  • Itemid -> внешний ключ к пунктам таблица
  • сообщение -> сообщение о событии

Там будет 100/1000s событий для каждого ItemID. Мне нужно, чтобы получить X самых новых событий из таблицы для каждого уникального значения itemid. В этом случае X равно 20, а «новейший» - самый высокий eventid.

Что я делал раньше, так это получение всего стола и сохранение только 20 самых новых для каждого элемента. Это очень медленно и неэффективно.

Edit: Я использую OpenNMS и таблицу событий (OpenNMS create.sql): (Itemid == NodeId)

create table events (
eventID integer not null, 
eventUei varchar(256) not null, 
nodeID integer, 
eventTime timestamp with time zone not null, 
eventHost varchar(256), 
eventSource varchar(128) not null, 
ipAddr varchar(16), 
eventDpName varchar(12) not null, 
eventSnmphost varchar(256), 
serviceID integer, 
eventSnmp varchar(256), 
eventParms text, 
eventCreateTime timestamp with time zone not null, 
eventDescr varchar(4000), 
eventLoggroup varchar(32), 
eventLogmsg varchar(256), 
eventSeverity integer not null, 
eventPathOutage varchar(1024), 
eventCorrelation varchar(1024), 
eventSuppressedCount integer, 
eventOperInstruct varchar(1024), 
eventAutoAction varchar(256), 
eventOperAction varchar(256), 
eventOperActionMenuText varchar(64), 
eventNotification varchar(128), 
eventTticket varchar(128), 
eventTticketState integer, 
eventForward varchar(256), 
eventMouseOverText varchar(64), 
eventLog char(1) not null, 
eventDisplay char(1) not null, 
eventAckUser varchar(256), 
eventAckTime timestamp with time zone, 
alarmID integer, 
constraint pk_eventID primary key (eventID) 
); 

Мой запрос был очень прост:

SELECT eventid, nodeid, eventseverity, eventtime, eventlogmsg 
FROM events 
WHERE nodeid IS NOT NULL; 
+1

Можете ли вы опубликовать свою структуру таблиц как «CREATE TABLE ...», примеры данных и ваш существующий запрос? –

+0

@IgorRomanchenko отредактировал сообщение с этими деталями – Smitty

ответ

2

Если вы хотите фиксированное количество «последних» записей, вам нужно использовать функцию окна row_number() (не rank()). Хотя, если eventid оказывается уникальным (за itemid), единственной (небольшой) разницей является производительность. (Ваше обновление вопроса подтверждает, что.)

Кроме того, вам нужен подзапрос для этого, так как WHERE условий применяются перед окна функции:

SELECT itemid, eventid, nodeid, eventseverity, eventtime, eventlogmsg 
FROM (
    SELECT itemid, eventid, nodeid, eventseverity, eventtime, eventlogmsg 
     ,row_number() OVER (PARTITION BY itemid 
          ORDER BY eventid DESC NULLS LAST) AS rn 
    FROM events 
    WHERE nodeid IS NOT NULL 
    ) sub 
WHERE rn <= 20 
ORDER BY 1, 2 DESC NULLS LAST; 

Предложение NULLS LAST относится только если eventid может быть NULL , и в этом случае это будет сортировать строки с значениями NULL до конца. (Ваши правила обновления для этого вопроса, поэтому предложение не требуется.)

1

Я бы предположить, что это это довольно дорого, и могут быть лучшие способы, но для вас что-то вроде этой работы?

select itemid, message 
from events e 
where eventid in 
    (select eventid from events f 
    where e.itemid=f.itemid 
    order by eventid desc 
    limit 20) 
order by itemid 

Подзапрос находит самые последние элементы для определенного элемента и внешний запрос делает это для всех элементов. Существует макет в sqlfiddle.

0
SELECT * FROM 
(SELECT 
    eventid, 
    itemid, 
    message, 
    rank() OVER (PARTITION BY itemid ORDER BY eventid DESC) AS rnk 
    FROM your_table) 
WHERE rnk <= 20 
Смежные вопросы