【问题标题】:How can I solve this & reach better performance我该如何解决这个问题并获得更好的性能
【发布时间】:2019-03-11 10:16:37
【问题描述】:

我们正在使用 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_lord_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

我知道这有点复杂且难以阅读,但我该如何解决这个问题并获得更好的性能?任何帮助将不胜感激。

【问题讨论】:

  • NVL 作用于单个值,而不是更复杂查询的结果。现在,由于您的代码以错误的方式使用了 NVL 函数,因此很难确定您想要实现什么。

标签: sql oracle oracle11g


【解决方案1】:

您不能使用来自两个selects 的nvl 返回许多列。

您想查找最新的日期和匹配的名称。 Union all 来自selects 和order byrownum 的数据都可以做到。

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% 了解预期),很难回答这样的问题,但也许这会有所帮助。

【讨论】:

  • 伙计,你太棒了。这就是我想要的。非常感谢。 ...是的,交货是我在这里的错误..(在 stackoverflow 上)。
猜你喜欢
  • 2020-03-25
  • 2020-02-14
  • 2021-10-23
  • 1970-01-01
  • 2021-07-31
  • 2020-12-28
相关资源
最近更新 更多