Как я могу решить эту проблему и достичь лучшей производительности - PullRequest
0 голосов
/ 11 марта 2019

Мы используем систему ERP, вот один запрос sql ниже - и он работает:

(используется старый синтаксис)

(select last_name||' '||name||'   '||to_char(datum_p,'DD.MM.YYYY') 
from
  (
   select co.kod_id, bu.last_name, bu.name, cl.datum_p, ctl.rid, md.short_name 
   from ord_odb_l cl, ord_odb_o co, b_users bu, ct_l ctl, m_delivery md
   where co.rid_o = cl.rid and bu.id = cl.operator and cl.delivery_place = md.rid 
   and cl.operator not IN (161,245,46,120,43,184) order by cl.datum_p desc
  ) aa 
where aa.kod_id = orders.SK_ID and aa.rid = orders.rid_ct_a 
and aa.short_name = orders.md and aa.datum_p > orders.datum_ok and rownum = 1)

Я хочу использовать NVL function для выбора имен и дат между заказами - распределение:

(но я думаю, что это невозможно с подзапросом или мне не удалось, , поскольку я получаю ошибку - missing right parenthesis)

(select last_name||' '||name||'   '||to_char(datum_p,'DD.MM.YYYY') 
from 
  (
   NVL(
    (select co.kod_id, bu.last_name, bu.name, cl.datum_p, ctl.rid, md.short_name
     from ord_odb_l cl, ord_odb_o co, b_users bu, ct_l ctl, m_delivery md 
     where co.rid_o = cl.rid and bu.id = cl.operator and cl.delivery_place = md.rid 
     and cl.operator not IN (161,245,46,120,43,184) order by cl.datum_p desc),

     (select vo.kod_id, bu.last_name, bu.name, vl.datum_p, ctl.rid, md.short_name 
     from distrb_l vl, distrb_o vo, b_users bu, ct_l ctl, m_delivery md
     where vo.rid_o = vl.rid and bu.id = cl.operator and cl.delivery_place = md.rid 
     and cl.operator not IN (161,245,46,120,43,184) order by vl.datum_p desc)
      )
   ) aa 
where aa.kod_id = orders.SK_ID and aa.rid = orders.rid_ct_a 
and aa.short_name = orders.md and aa.datum_p > orders.datum_ok and rownum = 1
)

Если нужно, мы можем присоединиться к distrb_l и ord_odb_l тоже:

(select * from ord_odb_l cl join distrb_l vl ON cl.rid = vl.rid_v)

для помощи:

У нас есть таблицы: ord_odb_l (заголовок заказов) и ord_odb_o (содержимое заказов), distrb_l (заголовок распределения) и distrb_o (содержимое распространения), b_users (таблица пользователей), ct_l (таблица цен), m_delivery (таблица доставки)

Столбцы: kod_id (число), last.name - name (varchar2), datum_p (дата), rid (число), short_name(varchar2), operator (число), delivery_place (число)

Фактическая таблица: orders

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

1 Ответ

1 голос
/ 11 марта 2019

Нельзя использовать nvl из двух select, возвращающих много столбцов.

Вы хотите найти самую новую дату и соответствующие имена.Union all данные из select s, тогда order by и rownum могут это сделать.

Строки из ord_odb_l имеют более высокий приоритет, строки из distrb_l являются вторичным источником данных.Таким образом, только если в первом запросе select нет данных, он будет возвращать что-то со второго:

(select last_name||' '||name||'   '||to_char(datum_p,'DD.MM.YYYY') 
  from (
    select 1 src, co.kod_id, bu.last_name, bu.name, cl.datum_p, ctl.rid, md.short_name
      from ord_odb_l  cl
      join ord_odb_o  co on co.rid_o = cl.rid 
      join b_users    bu on bu.id = cl.operator 
      cross join ct_l ctl
      join m_delivery md on cl.delivery_place = md.rid
      where cl.operator not IN (161,245,46,120,43,184) 
    union all 
    select 2 src, vo.kod_id, bu.last_name, bu.name, vl.datum_p, ctl.rid, md.short_name 
      from distrb_l   vl
      join distrb_o   vo on vo.rid_o = vl.rid
      join b_users    bu on bu.id = cl.operator
      cross join ct_l ctl
      join m_delivery md on cl.delivery_place = md.rid
      where cl.operator not IN (161,245,46,120,43,184) 
      order by src, datum_p desc) aa 
  where aa.kod_id = orders.SK_ID and aa.rid = orders.rid_ct_a 
    and aa.short_name = orders.md and aa.datum_p > orders.datum_ok and rownum = 1)

Ваш запрос является частью большего, возможно, подселекта, потому что мы не видим здесь, что являетсяorders и т. Д. Вероятно, вы можете упростить эту задачу, но без всего изображения сложно сказать больше.В любом случае это должно работать.Обратите внимание, что я изменил синтаксис на join форму.Таблица ct_l не имеет условия соединения в ваших запросах, поэтому используется cross join, это правильно?Был также derlivery вместо delivery.

Еще одна вещь.Я предположил, что строки из первой таблицы имеют более высокий приоритет, потому что это предполагает ваш код.Если вам нужна строка с самой новой датой, независимо от того, какая таблица, тогда используйте order by datum_p desc вместо order by src, datum_p desc.

Также в Oracle 12 вы можете использовать fetch first row only, но вопрос помечен как Oracle 11g..

Как вы заметили, трудно ответить на такой вопрос без доступа к данным, структуры (и без ожидания на 100%), но, возможно, это поможет.

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