Как выбрать k-ю запись для каждого поля в одном запросе SQL - PullRequest
0 голосов
/ 24 мая 2019

, пожалуйста, помогите мне решить следующую проблему. Я потратил уже неделю, пытаясь объединить всю логику в одном SQL-запросе, но все еще не получил изящного результата. Я надеюсь, что эксперты SQL могли бы дать мне подсказку,

У меня есть таблица, которая имеет 4 поля: дата, expire_month, expire_year и значение. Первичный ключ определен в 3 первых полях. Таким образом, для конкретной даты имеется несколько значений с разными expire_month, expire_year. Мне нужно выбрать одно значение из них для каждой даты, представленной в таблице.

Например, когда я выполняю запрос:

SELECT date, expire_month, expire_year, value FROM futures 
WHERE date = ‘1989-12-01' ORDER BY expire_year, expire_month;

Я получаю список значений на ту же дату, отсортированный по сроку действия (месяцы кодируются буквами):

1989-12-01  Z   1989    408.25
1989-12-01  H   1990    408.25
1989-12-01  K   1990    389
1989-12-01  N   1990    359.75
1989-12-01  U   1990    364.5
1989-12-01  Z   1990    375

Правильным единственным значением для этой даты является k-я запись сверху. Например, если k равно 2, тогда «правильная одиночная» запись будет:

1989-12-01  H   1990    408.25

Как я могу выбрать эти «правильные одиночные» значения для каждой даты в моей таблице?

Ответы [ 3 ]

2 голосов
/ 24 мая 2019

Вы можете сделать это с помощью rank():

select t.date, t.expire_month, t.expire_year, t.value from (
  select *,
    rank() over(partition by date order by expire_year, expire_month) rn
  from futures 
) t
where t.rn = 2

Столбец rn в подзапросе фактически является рангом строки, сгруппированной по date.
Измените 2 на тот уровень, который вам нужен.

1 голос
/ 24 мая 2019

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

SELECT date, expire_month, expire_year, value
FROM futures AS f
WHERE (date, expire_month, expire_year) =
      (SELECT f2.date, f2.expire_month, f2.expire_year
       FROM futures AS f2
       WHERE f.date = f2.date
       ORDER BY f2.expire_year, f2.expire_month
       LIMIT 1 OFFSET 1)
ORDER BY date;

Значение OFFSET на 1 меньше, чем строка Kth - поэтому 1 для второй строки, 2 длятретья строка и т. д.

Он выполняет коррелированный подзапрос для каждой строки в таблице, что не является идеальным.Надеемся, что ваши составные столбцы первичного ключа имеют порядок date, expire_year, expire_month, что очень поможет, устраняя необходимость в дополнительной сортировке в нем.

0 голосов
/ 24 мая 2019

Вы можете попробовать следующий запрос.

select * from 
(
SELECT rownum seq, date1, expire_month, expire_year, value FROM testtable
WHERE date1 = to_date('1989-12-01','yyyy-mm-dd') 
ORDER BY expire_year, expire_month
)
where seq=2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...