#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).