Запутанная инструкция SELECT - PullRequest
3 голосов
/ 01 марта 2011

Сначала я покажу вам примеры таблиц, к которым относится моя проблема, затем я задам вопрос.

[my_fruits]
fruit_name   |   fruit_id   | fruit_owner   |   fruit_timestamp
----------------------------------------------------------------
Banana       |   3          |  Timmy        |   3/4/11
Banana       |   3          |  Timmy        |   4/1/11
Banana       |   8          |  Timmy        |   5/2/11
Apple        |   4          |  Timmy        |   2/1/11
Apple        |   4          |  Roger        |   3/4/11

Теперь я хочу запустить запрос, который выбирает только значения fruit_name, fruit_id и fruit_owner. Я хочу получить только один ряд на фрукт, и способ, которым я хочу, чтобы это было решено, является самой последней отметкой времени. Например, идеальный запрос к этой таблице будет возвращать:

[my_fruits]
fruit_name   |   fruit_id   | fruit_owner   |
----------------------------------------------
Banana       |   8          |  Timmy        |
Apple        |   4          |  Roger        | 

Я попробовал запрос:

select max(my_fruits.fruit_name) keep 
    (dense_rank last order by my_fruits.fruit_timestamp) fruit_name,
       my_fruits.fruit_id, my_fruits.fruit_owner 
from my_fruits 
group by my_fruits.fruit_id, my_fruits.fruit_owner

Теперь проблема заключается в том, что возвращаются в основном разные названия фруктов, идентификаторы фруктов и владельцы фруктов.

Ответы [ 4 ]

3 голосов
/ 01 марта 2011

Для Oracle 9i + используйте:

SELECT x.fruit_name,
       x.fruit_id,
       x.fruit_owner
  FROM (SELECT mf.fruit_name,
               mf.fruit_id,
               mf.fruit_owner,
               ROW_NUMBER() OVER (PARTITION BY mf.fruit_name
                                      ORDER BY mf.fruit_timestamp) AS rank
          FROM MY_FRUIT mf) x
 WHERE x.rank = 1

Большинство баз данных будут поддерживать использование самостоятельного соединения с производной таблицей / встроенным представлением:

SELECT x.fruit_name,
       x.fruit_id,
       x.fruit_owner
  FROM MY_FRUIT x
  JOIN (SELECT t.fruit_name,
               MAX(t.fruit_timestamp) AS max_ts
          FROM MY_FRUIT t
      GROUP BY t.fruit_name) y ON y.fruit_name = x.fruit_name
                              AND y.max_ts = x.fruit_timestamp

Однако это вернет дубликаты, если есть 2+ записи fruit_name с одинаковым значением временной метки.

2 голосов
/ 02 марта 2011

Если вам нужно по одной строке на название фрукта, вам нужно сгруппировать по названию фрукта.

select fruit_name,
       max(my_fruits.fruit_id) keep 
          (dense_rank last order by my_fruits.fruit_timestamp) fruit_id,
       max(my_fruits.fruit_owner) keep 
          (dense_rank last order by my_fruits.fruit_timestamp) fruit_owner
from my_fruits 
group by my_fruits.fruit_name

Как вы хотите бороться с тай-брейками - это отдельная проблема.

1 голос
/ 01 марта 2011

Попробуйте подзапрос:

select a.fruit_name, a.fruit_id, a.fruit_owner
from my_fruits a
where a.fruit_timestamp =
 (select max(b.fruit_timestamp)
  from my_fruits b
  where b.fruit_id = a.fruit_id)
0 голосов
/ 01 марта 2011

Я бы сделал это, выяснив список (fruit_name, fruit_timestamp), которые вас интересуют, а затем сгруппировав эту «таблицу» с реальной таблицей фруктов и получив другие значения.

SELECT fruit_and_max_t.fruit_name, 
       my_fruits.fruit_id,
       my_fruits.fruit_owner
FROM my_fruits, 
  ( SELECT fruit_name, MAX(fruit_timestamp) AS max_timestamp
    FROM my_fruits
    GROUP BY fruit_name) AS fruit_and_max_t,
WHERE fruit_and_max_t.max_timestamp = my_fruits.fruit_timestamp
  AND fruit_and_max_t.fruit_name    = my_fruits.fruit_name

Это предполагает, что в таблице нет нескольких записей с одинаковым значением (fruit_name, fruit_timestamp), т. Е. Кортеж (пара) действует как уникальный идентификатор.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...