Как переписать длинный запрос? - PullRequest
1 голос
/ 11 мая 2010

У меня есть следующие 2 таблицы:

items:
 id int primary key
 bla text

events:
 id_items int
 num int
 when timestamp without time zone
 ble text
 composite primary key: id_items, num

и хотите выбрать для каждого элемента самое последнее событие (самое новое «когда»). Я написал запрос, но я не знаю, может ли он быть написан более эффективно. Также в PostgreSQL есть проблема со сравнением объектов Timestamp: 2010-05-08T10: 00: 00.123 == 2010-05-08T10: 00: 00.321 поэтому я выбираю с помощью «MAX (номер)» Есть мысли как сделать лучше? Спасибо.

SELECT i.*, ea.* FROM items AS i JOIN
( SELECT t.s AS t_s, t.c AS t_c, max(e.num) AS o FROM events AS e JOIN
( SELECT DISTINCT id_item AS s, MAX(when) AS c FROM events GROUP BY s ORDER BY c ) AS t
ON t.s = e.id_item AND e.when = t.c GROUP BY t.s, t.c ) AS tt
ON tt.t_s = i.id JOIN events AS ea ON ea.id_item = tt.t_s AND ea.cas = tt.t_c AND ea.num = tt.o;

РЕДАКТИРОВАТЬ : были плохие данные, извините, мои плохие, однако спасибо за поиск лучшего SQL-запроса

Ответы [ 3 ]

0 голосов
/ 11 мая 2010

Если вы используете 8.4:

select * from (
  select item.*, event.*,
         row_number() over(partition by item.id order by event."when" desc) as row_number
  from items item
       join events event on event.id_items = item.id
) x where row_number = 1
0 голосов
/ 11 мая 2010

Для этого типа соединений я предпочитаю синтаксис DISTINCT ON ( пример ). Это расширение Postgresql (не стандартный синтаксис SQL), но оно поставляется очень удобно:

SELECT DISTINCT ON (it.id) 
it.*, ev.*
FROM items it, events ev
WHERE ev.id_items = it.id
ORDER by it.id, ev.when DESC;

С точки зрения простоты и читабельности это невозможно.

В этом запросе предполагается, что у каждого элемента есть хотя бы одно событие. Если нет, и если вы хотите все события, вам нужно внешнее соединение:

SELECT DISTINCT ON (it.id) 
it.*, ev.*
FROM items it LEFT JOIN events ev
ON ev.id_items = it.id
ORDER BY it.id, ev.when DESC;

КСТАТИ: в Postgresql нет "проблемы с отметкой времени" , возможно, вам следует изменить заголовок.

0 голосов
/ 11 мая 2010
SELECT  (i).*, (e).*
FROM    (
        SELECT  i,
                (
                SELECT  e
                FROM    events e
                WHERE   e.id_items = i.id
                ORDER BY
                        when DESC
                LIMIT 1
                ) e
        FROM    items i
        ) q
...