powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Подскажите правильное решение задачи
21 сообщений из 21, страница 1 из 1
Подскажите правильное решение задачи
    #39647716
julat21
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть задача, которую необходимо решить на Oracle. Всегда пытаюсь решить задачу в лоб, с точки зрения логики. Быстро пришел только к этому решению:


Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
SELECT aa.*
      , a.val 
 FROM( SELECT b.*, (SELECT MAX(a.dt) 
                      FROM a 
                     WHERE a.cur = b.cur 
                       AND b.dt>=a.dt 
                       ) as dtcurs 
                   FROM b
) aa, a
WHERE aa.cur = a.cur
AND aa.dtcurs = a.dt
...
Рейтинг: 0 / 0
Подскажите правильное решение задачи
    #39647722
MaximaXXL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
julat21,

Внимание вопрос: - Какую задачу я решал?
...
Рейтинг: 0 / 0
Подскажите правильное решение задачи
    #39647727
julat21
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MaximaXXL,Не могу фото загрузить. Ни один хостинг картинок не грузит.
...
Рейтинг: 0 / 0
Подскажите правильное решение задачи
    #39647730
julat21
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MaximaXXL,
...
Рейтинг: 0 / 0
Подскажите правильное решение задачи
    #39647733
dmdmdm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кнопочка "выберите файл".
Но картинкой - это неправильно.

Исходные данные с with, описание логики задачи.
...
Рейтинг: 0 / 0
Подскажите правильное решение задачи
    #39647735
julat21
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот,
...
Рейтинг: 0 / 0
Подскажите правильное решение задачи
    #39647741
julat21
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dmdmdm,
...
Рейтинг: 0 / 0
Подскажите правильное решение задачи
    #39647744
Фотография Щукина Анна
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
julat21,

ваша задача, по сути, сводится к поиску "максимума снизу". в основу решения можно положить любой из методов, описанных тут
...
Рейтинг: 0 / 0
Подскажите правильное решение задачи
    #39647745
julat21
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Щукина Анна,
Я так и решал(Первое сообщение). Но решение не оптимальное. Есть другой способ, который мне неизвестен. Допустим с первой таблицы получить таблицу интервалов как-то или еще что-то...
...
Рейтинг: 0 / 0
Подскажите правильное решение задачи
    #39647751
Фотография Щукина Анна
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
julat21,

Вы не так решали. Коррелированные скалярный подзапрос в списке Select - даже не рассматривался как решение по приведенной ссылке... В предложении WHERE - да, но не в SELECT...
Ваша задача сводится к джойну по неэкви-условию с последующей "фильтрацией" данных по любому из способов по ссылке.
Можно натянуть её на рекурсивный WITH (если версия оракла позволяет - от 11g и выше). Возможно удастся получить "красивое" и эффективно использующее индексы (если таковые имеются и подходят под задачу) решение...
...
Рейтинг: 0 / 0
Подскажите правильное решение задачи
    #39647757
Фотография Щукина Анна
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
julat21,

почитайте про LAST/FIRST агрегатный. Вся ваша задача - это линейный запрос из B, в Select-листе которого одним из полей будет коррелированный скаляр к таблице A по условию соединения B.Dt >= A.Dt и выборкой нужного курса при помощи max(val) keep (dense_rank first order by a.dt desc)
...
Рейтинг: 0 / 0
Подскажите правильное решение задачи
    #39647758
julat21
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Щукина Анна,
подскажите, пожалуйста, посмотрел все 6 вариантов, которые Вы указали по ссылке. Но они не учитывают, что необходимо учитывать даты не просто MAX по таблице А с группировкой по CUR, а на каждую строчку В необходимо учитывать, что дата в А меньше... Просто с JOIN два разных множества, я думаю, не решат задачу, даже с фильтрацией.
...
Рейтинг: 0 / 0
Подскажите правильное решение задачи
    #39647759
Фотография Щукина Анна
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Само собой, ещё по типу валюты нужно вязать таблицы:
Щукина Аннаjulat21,

почитайте про LAST/FIRST агрегатный. Вся ваша задача - это линейный запрос из B, в Select-листе которого одним из полей будет коррелированный скаляр к таблице A по условию соединения B.Dt >= A.Dt and a.cur= b.cur и выборкой нужного курса при помощи max(val) keep (dense_rank first order by a.dt desc)

такое неплохо ляжет на индекс, хоть и будет бегать нестед-лупсами.

P.S.
Почитать про FIRST в офф.доке , в блоках на Sql.ru
...
Рейтинг: 0 / 0
Подскажите правильное решение задачи
    #39647762
Фотография Щукина Анна
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
julat21Щукина Анна,
подскажите, пожалуйста, посмотрел все 6 вариантов, которые Вы указали по ссылке. Но они не учитывают, что необходимо учитывать даты не просто MAX по таблице А с группировкой по CUR, а на каждую строчку В необходимо учитывать, что дата в А меньше... Просто с JOIN два разных множества, я думаю, не решат задачу, даже с фильтрацией.вы дали картиночное описание задачи, я - словесное решение. :)
Хотите конкретики - приведите удобные для использования тестовые данные в виде with (select ...)

если схематично, то решение будет выглядеть так:
Код: plsql
1.
2.
3.
4.
select b.*
     , (select max(val) keep (dense_rank first order by a.dt desc) 
         from a where a.cur = b.cur and a.dt <= b.dt) x_cur
from b
...
Рейтинг: 0 / 0
Подскажите правильное решение задачи
    #39647763
oragraf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
julat21,

если бы ты не поленился и сделал исходные данные в виде with - тебе дали бы уже решение.
...
Рейтинг: 0 / 0
Подскажите правильное решение задачи
    #39647765
Фотография Щукина Анна
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Щукина Аннаjulat21Щукина Анна,
подскажите, пожалуйста, посмотрел все 6 вариантов, которые Вы указали по ссылке. Но они не учитывают, что необходимо учитывать даты не просто MAX по таблице А с группировкой по CUR, а на каждую строчку В необходимо учитывать, что дата в А меньше... Просто с JOIN два разных множества, я думаю, не решат задачу, даже с фильтрацией.вы дали картиночное описание задачи, я - словесное решение. :)
Хотите конкретики - приведите удобные для использования тестовые данные в виде with (select ...)

если схематично, то решение будет выглядеть так:
Код: plsql
1.
2.
3.
4.
select b.*
     , (select max(val) keep (dense_rank first order by a.dt desc) 
         from a where a.cur = b.cur and a.dt <= b.dt) x_cur
from b

скалярный подзапрос можно переписать на джойн. возможно, это позволит ораклу оптимальнее выполнить запрос.
оно во многом будет завиветь от схемы индексирования и от того, как именно количественно распределены данные по таблицам...
...
Рейтинг: 0 / 0
Подскажите правильное решение задачи
    #39647767
julat21
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Щукина Анна,

Спасибо.
...
Рейтинг: 0 / 0
Подскажите правильное решение задачи
    #39647770
Фотография Щукина Анна
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
julat21,

возможно, "примерный" аналог на JOIN:
Код: plsql
1.
2.
3.
4.
5.
6.
select b.*
     , max(a.val) keep (dense_rank first order by a.dt desc) as x_cur
from b
join a on a.cur = b.cur
and a.dt <= b.dt
group by b.cur, b.dt
...
Рейтинг: 0 / 0
Подскажите правильное решение задачи
    #39647775
julat21
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Щукина Анна, Спасибо большое.
...
Рейтинг: 0 / 0
Подскажите правильное решение задачи
    #39647826
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот пара-тройка вариантов "на вскидку", развлекайтесь.

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
with a_ver(cur, val, dt_from, dt_till) 
  as ( select cur, val, dt dt_from
            , lead(dt,1,date'3000-01-01') over(partition by cur order by dt)-1/86400 dt_till
         from a )
select b.cur, b.dt, a.val
from b left join a_ver a on a.cur = b.cur and b.dt between a.dt_from and a.dt_till
;

select b.cur, b.dt, max(a.val) keep (dense_rank last order by a.dt) val
from b left join a on a.cur = b.cur and b.dt >= a.dt
group by b.cur, b.dt
;

select b.cur, b.dt, a.val
from b, lateral(select val from a where a.cur=b.cur and a.dt <= b.dt order by a.dt desc fetch first 1 row only) a 
;

select b.cur, b.dt, (select val from a where a.cur=b.cur and a.dt <= b.dt order by a.dt desc fetch first 1 row only) val
from b  
;

with uni as (
select 'a' g, cur, dt, val from a 
union all
select 'b', b.cur, b.dt, null val from b  
)
select *
from uni 
match_recognize(
partition by cur
order by dt desc, g desc
measures first(b.dt) as dt, a.val as val
after match skip to next row
pattern (b+ a)
define b as b.g='b', a as a.g='a'
)
;


with uni as (
select 'a' g, cur, dt, val from a 
union all
select 'b', b.cur, b.dt, null val from b  
)
select cur, dt, val 
  from ( select g, cur, dt, lag(val ignore nulls) over(partition by cur order by dt, g) val
           from uni)
where g='b'
order by cur, dt
;
...
Рейтинг: 0 / 0
Подскажите правильное решение задачи
    #39647883
Dshedoo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
with a (cur, dt, val) as (
select 'USD', to_date('25.10.2009'), 26.9307 from dual union all
select 'USD', to_date('28.10.2009'), 26.7884 from dual union all
select 'USD', to_date('31.10.2009'), 26.7477 from dual union all
select 'EUR', to_date('25.10.2009'), 33.7603 from dual union all
select 'EUR', to_date('26.10.2009'), 33.8003 from dual union all
select 'EUR', to_date('28.10.2009'), 33.9677 from dual union all
select 'EUR', to_date('31.10.2009'), 34.0284 from dual)
, b (cur, dt) as (
select 'USD', to_date('27.10.2009') from dual union all
select 'USD', to_date('28.10.2009') from dual union all
select 'USD', to_date('29.10.2009') from dual union all
select 'EUR', to_date('27.10.2009') from dual union all
select 'EUR', to_date('28.10.2009') from dual union all
select 'EUR', to_date('29.10.2009') from dual union all
select 'EUR', to_date('01.11.2009') from dual)

select * from (select b.cur, b.dt, a.val, dense_rank() OVER (partition by b.dt, b.cur order by a.dt desc) as rn
from b left join a on b.cur = a.cur and a.dt <= b.dt)
where rn = 1 order by cur desc, dt
...
Рейтинг: 0 / 0
21 сообщений из 21, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Подскажите правильное решение задачи
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]