Как я могу решить это и повысить производительность

#sql #oracle #oracle11g

#sql #Oracle #oracle11g

Вопрос:

Мы используем 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. NVL работает с одним значением, а не с результатом более сложного запроса. Теперь, поскольку ваш код неправильно использует функцию NVL, трудно определить, чего именно вы хотите достичь.

Ответ №1:

Вы не можете использовать nvl from two select s, возвращающий много столбцов.

Вы хотите найти самую последнюю дату и соответствующие имена. Union all данные из обоих select тогда 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 form. Таблица 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%-ного знания ожиданий), но, возможно, это поможет.

Комментарии:

1. Чувак, ты потрясающий. Это то, чего я хотел. Большое спасибо. … да, derlivery был моей ошибкой здесь.. (в stackoverflow).