Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Подскажите правильное решение задачи / 21 сообщений из 21, страница 1 из 1
21.05.2018, 18:42
    #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
21.05.2018, 18:58
    #39647722
MaximaXXL
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Подскажите правильное решение задачи
julat21,

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

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

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

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

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

если бы ты не поленился и сделал исходные данные в виде with - тебе дали бы уже решение.
...
Рейтинг: 0 / 0
21.05.2018, 20:44
    #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
21.05.2018, 20:49
    #39647767
julat21
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Подскажите правильное решение задачи
Щукина Анна,

Спасибо.
...
Рейтинг: 0 / 0
21.05.2018, 20:53
    #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
21.05.2018, 21:06
    #39647775
julat21
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Подскажите правильное решение задачи
Щукина Анна, Спасибо большое.
...
Рейтинг: 0 / 0
22.05.2018, 04:29
    #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
22.05.2018, 09:08
    #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
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Подскажите правильное решение задачи / 21 сообщений из 21, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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