powered by simpleCommunicator - 2.0.52     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Помогите улучшить запрос
16 сообщений из 16, страница 1 из 1
Помогите улучшить запрос
    #39950205
Евгения_Д
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Доброе время суток!
Помогите пожалуйста улучшить запрос.
Есть таблица table_a, в ней поле cust_ID и
таблица table_b, в ней поле cust_ID и doc_date.
В table_b м.б. несколько записей с одним cust_ID и разными doc_date, в т.ч. одинаковыми.
Надо соединить по cust_ID строку из table_a с ОДНОЙ строкой из table_b, с максимальной датой.
Если даты одинаковые, то первая, какая нашлась.
Я сделала с помощью CTE
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
WITH
    t1
    AS
      (SELECT cust_id, rowid
         FROM table_b 
        ORDER BY cust_id, doc_date
        )

select b.*
  from table_a a
  JOIN table_b B
       ON B.cust_ID = A.CUST_ID
       AND B.rowid = (SELECT rowid FROM t1
                          WHERE cust_ID = B.cust_ID
                            AND rownum = 1)


Но я думаю, что CTE не очень эффективно, с точки зрения потребления ресурсов.
Подскажите, как можно улучшить запрос?
...
Рейтинг: 0 / 0
Помогите улучшить запрос
    #39950218
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Евгения_Д

Я сделала с помощью CTE

Ну и где тут CTE?

Впрочем, вот вам пара типовых вариантов, играйтесь:
Код: 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.
select a.*, b.*
  from table_a a
  cross apply (select * from table_b where cust_ID = A.CUST_ID order by doc_date desc fetch first 1 row only) b
;

select a.*, b.*
  from table_a a
     , lateral (select * from table_b 
                where cust_ID = A.CUST_ID 
                order by doc_date desc fetch first 1 row only) b
;

select a.*, b.*
from table_b
  match_recognize(
    partition by cust_ID 
    order by doc_date desc 
    measures strt.doc_date as doc_date
    one row per match
    pattern(strt x*)
    define x as cust_id is not null
  ) b
join table_a a on a.cust_id = b.cust_id
;

select a.*, b.*
  from table_a a
  join ( select cust_id
              , max(doc_date) doc_date 
             -- , max(someOtherField) keep (dense_rank first order by doc_date desc, rowid) someOtherField -- для полей, отличных от cust_id и doc_date
           from table_b group by cust_ID) b
    on B.CUST_ID  = A.CUST_ID 
;

select a.*, b.cust_id, b.doc_date
  from table_a a
  join ( select bb.*
              , lag(null,1,1) over(partition by cust_id order by doc_date desc) f
           from table_b bb) b
    on B.CUST_ID  = A.CUST_ID and b.f=1
;

...
Рейтинг: 0 / 0
Помогите улучшить запрос
    #39950230
Фотография Кобанчег
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymous
Евгения_Д

Я сделала с помощью CTE

Ну и где тут CTE?
У девушки такие же предпчтения как у Льюиса. Разве стоит её за это критиковать?
https://jonathanlewis.wordpress.com/2014/02/16/recursive-subquery-factoring/ Personally I prefer to use the expression CTE – common table expression – over “factored subquery” or “subquery factoring” or “with subquery”
...
Рейтинг: 0 / 0
Помогите улучшить запрос
    #39950310
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymous,

1) плохой вариант?
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
SQL> ed
Wrote file afiedt.buf

  1  select * from (
  2    select a.*,b.empno,b.hiredate,b.sal
  3    ,row_number() over (partition by b.deptno order by hiredate)  rn
  4   from dept a,emp b where b.deptno=a.deptno)
  5* where rn=1
SQL> /

    DEPTNO DNAME          LOC                EMPNO HIREDATE          SAL         RN
---------- -------------- ------------- ---------- ---------- ---------- ----------
        10 ACCOUNTING     NEW YORK            7782 09.06.1981       2450          1
        20 RESEARCH       DALLAS              7369 17.12.1980        800          1
        30 SALES          CHICAGO             7499 20.02.1981       1600          1



2) pattern(x+) хуже?
.....
stax
...
Рейтинг: 0 / 0
Помогите улучшить запрос
    #39950317
Евгения_Д
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
andrey_anonymous

Ну и где тут CTE?


А разве это не CTE?
Код: plsql
1.
2.
3.
WITH 
    t1
    AS (...)



А за варианты спасибо!
Именно то, что хотелось. Буду смотреть.
...
Рейтинг: 0 / 0
Помогите улучшить запрос
    #39950372
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax


1) плохой вариант?

Почему сразу плохой?
Просто я предпочитаю (по возможности и осмысленности) декларировать агрегации и "фильтр-аналитику"
на потенциально меньшем наборе и уже потом соединять результат с прочими наборами.
Блин, вот написал предложение - и теперь либо пиши целую статью когда этого не надо делать, или обтекай.
Буду обтекать, ибо писать статьи не обучен :)

Stax

2) pattern(x+) хуже?

Не люблю его - заставляет размышлять над define, чтобы не упустить первую запись группы.
...
Рейтинг: 0 / 0
Помогите улучшить запрос
    #39950377
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Евгения_Д
andrey_anonymous

Ну и где тут CTE?

А разве это не CTE?

Поправлюсь: ну и где тут CTE, которое помогло решить задачу?
В данном варианте это просто вынесенная декларация inline view, никакого влияния ни на исполнение, ни на декларацию запроса не оказавшее:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
select b.*
  from table_a a
  JOIN table_b B
       ON B.cust_ID = A.CUST_ID
       AND B.rowid = (SELECT rid FROM (SELECT cust_id, rowid rid
                         FROM table_b 
                        ORDER BY cust_id, doc_date
                        )
      WHERE cust_ID = B.cust_ID
        AND rownum = 1)
...
Рейтинг: 0 / 0
Помогите улучшить запрос
    #39950391
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymous
Stax


1) плохой вариант?

Почему сразу плохой?
Просто я предпочитаю (по возможности и осмысленности) декларировать агрегации и "фильтр-аналитику"
на потенциально меньшем наборе и уже потом соединять результат с прочими наборами.
Блин, вот написал предложение - и теперь либо пиши целую статью когда этого не надо делать, или обтекай.
Буду обтекать, ибо писать статьи не обучен :)

Stax

2) pattern(x+) хуже?

Не люблю его - заставляет размышлять над define, чтобы не упустить первую запись группы.


об 1) я забыл написать что для случая когда по id в table_b есть индекс (аля сначала соеденить, а потом фильтр)

2) так для такого случая define всеравно вынужден(фальшивый)
pattern(strt+ x*)
define x as cust_id is not null
я так понимаю даж is not null не будет проверятся

....
stax
...
Рейтинг: 0 / 0
Помогите улучшить запрос
    #39950404
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax
1) я забыл написать что для случая когда по id в table_b есть индекс (аля сначала соеденить, а потом фильтр)
Ну начинаааается...
Если соединение с table_a заметно снижает мощность результирующего множества в сравнении с подмножеством table_b - то лучше анализировать/группировать соединение.
Если соединение с table_a не влияет или даже увеличивает мощность результирующего множества в сравнении с подмножеством table_b - то, на мой взгляд, уместнее провести аналитические/агрегирующие/сортирующие операции над более скромным (за счет отсутствия в подмножестве table_b атрибутов table_a) множеством.
Как-то так.
Нет, не спрашивайте. Я сам запутался :)
Stax

2) так для такого случая define всеравно вынужден

Define по синтаксису положен.
Однако в обсуждаемом варианте, вообще говоря, не так уж важно, что именно там написано - лишь бы не порвало группу раньше времени.
По поводу "не будет выполняться" - сомнительно. AFAIK pattern matching не умеет обрывать поиск а-ля "count stop key", он все равно вычерпает rowsource до конца и честно применит pattern.
...
Рейтинг: 0 / 0
Помогите улучшить запрос
    #39950405
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Евгения_Д,
еще вариант:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
select b.*
  from table_a a
  JOIN table_b B
       ON B.cust_ID = A.CUST_ID
Where
       B.rowid in (SELECT  MAX(t1.rowid) KEEP ( DENSE_RANK LAST ORDER BY t1.doc_date) as z_rowid
                        FROM table_b t1
                        Group by t1.cust_id
                      )


Это подходит под условие "любой из тех, что с одной и той же датой ".

У вас, кстати, дефект сортировки.
В вашем варианте надо писать ORDER BY cust_id, doc_date desc
...
Рейтинг: 0 / 0
Помогите улучшить запрос
    #39950564
Фотография Кобанчег
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax
не будет проверятся
Шаблон применяется ко всем строкам rowsource как уже сообщил синьор Эндрю.

Если гарантированно не нужны строки строки замапленные на определенную переменную шаблона (синтаксис {--}) то и в этом случае будет сначала проверка соответствуют ли строки этой переменной.

Есть же стандартный дедовский метод [не дающий никаких гарантий] чтоб проверить вызовы.

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
select *
from t
match_recognize
(
  measures strt.id y
  pattern (strt {-x-}+)
  define x as f(x.id) is not null
)


Код: plsql
1.
2.
3.
4.
5.
create or replace function f(i in int) return int is
begin
  dbms_lock.sleep(1);
  return i;
end f;



Еще раз для ясности: все строки будут проверены на соответсвие шаблону даже если никакие строки кроме первой не интересуют.
В этом инструменте [пока?] нет средств ограничить выполнение как в аналитике типа WINDOW ... STOPKEY или WINDOW ... PUSHED RANK.

Также стоит уточнить, что если вдруг интересует только первый match_number, то в текущей реализации нет средств остановить проверку после получения первой заматченой группы.

Читай страницу 43-44 DEEP DIVE INTO 12c MATCH_RECOGNIZE.
...
Рейтинг: 0 / 0
Помогите улучшить запрос
    #39950601
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кобанчег
Шаблон применяется ко всем строкам rowsource как уже сообщил синьор Эндрю.


это мне было понятно сразу

я про какой патерн луче

1) pattern(strt x*) cust_id is not null вычисляется для всех строк в партиции кроме первой
2) pattern(x+) cust_id is not null вычисляется для всех строк
3) pattern(strt+ x) cust_id is not null вычисляется не будет


зы
насколько я понял х в pattern надо указывать

.....
stax
...
Рейтинг: 0 / 0
Помогите улучшить запрос
    #39950639
Фотография Кобанчег
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax
насколько я понял х в pattern надо указывать
Обязательна кляуза define, но не обязательны правила для всех pattern variables.

Просто как пример
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
select *
from t
match_recognize
(
  measures strt.id y
  pattern (strt {-x-}+)
  define strt as 1 = 1
);


Я надеюсь это разговор из академического интереса поскольку pattern matching - абсурдный подход
для того чтоб взять первую строку из группы (будь то с сортировкой или без).
...
Рейтинг: 0 / 0
Помогите улучшить запрос
    #39950642
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кобанчег
Stax
насколько я понял х в pattern надо указывать
Обязательна кляуза define, но не обязательны правила для всех pattern variables.

Просто как пример
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
select *
from t
match_recognize
(
  measures strt.id y
  pattern (strt {-x-}+)
  define strt as 1 = 1
);


Я надеюсь это разговор из академического интереса поскольку pattern matching - абсурдный подход
для того чтоб взять первую строку из группы (будь то с сортировкой или без).


интерес академический (другого у меня счас нет)

я имел ввиду что так нельзя

Код: plsql
1.
2.
    pattern(strt+)
    define x as deptno is not null



если х описан в define то его надо использовать в pattern

pattern(х+) можно

.....
stax
...
Рейтинг: 0 / 0
Помогите улучшить запрос
    #39950664
Фотография Кобанчег
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stax,

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

Казалось бы зачем может прийти в голову определять правило для несуществующей переменной шаблона...

для фичи
Кобанчег
Обязательна кляуза define,
но не обязательны правила для всех pattern variables.


.....
stax
...
Рейтинг: 0 / 0
16 сообщений из 16, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Помогите улучшить запрос
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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