0

Oracle 在下一个查询中表现得非常奇怪:

我正在尝试评估这三个记录,其中一个应该显示列digitado = 1,因为它满足所有条件,它们是,NUM_DOCUMENTO_ENCABEZADO iS NOT NULL and ORIGEN_PLANILLA = 2

NUM_DOCUMENTO   NUM_DOCUMENTO_ENCABEZADO    ORIGEN_PLANILLA
8220568059                8220568059                    2
8220681644                                              2
940723593097                                        1


select  x.num_documento,
        x.origen_planilla,
        x.num_documento_encabezado,
        case    
                when  x.num_documento_encabezado > '0' and x.origen_planilla = 2  then 
                    1 
                else 
                    0
        end digitado
from    (
            select  h.num_documento,
                    h.num_documento_encabezado,
                    h.origen_planilla
            from    (
                        select  a.num_documento,
                                c.num_documento num_documento_encabezado,
                                case when NVl(UPPER(a.txt_observacion),'X') like '%SGP%' THEN 1 ELSE 2 END origen_planilla
                        from    epsis.ryc_recaudo               a,
                                epsis.ryc_recaudo_unificado     b,
                                epsis.ryc_documento_encabezado  c
                        where a.fec_pago            >=  to_date('28082013','ddmmyyyy') ---aca se coloca el dia del ultimo proceso,
                        and     a.fec_pago          <   to_date('25092013','ddmmyyyy')-- el cecaudo viene un dia atrasados
                        and     b.num_documento(+)  =   a.num_documento
                        and     c.num_documento(+)  =   b.num_documento --80595
                        and     a.num_documento     in  ( '940723593097', '8220681644','8220568059')
                    ) h,
                    epsis.ryc_divide_documento f,
                    epsis.ryc_documento_encabezado g
            where   f.num_documento(+) = h.num_documento
            and     g.num_documento(+) =f.num_division
            group by  h.num_documento,
                    h.num_documento_encabezado,
                    h.origen_planilla
        ) x

这是结果:

NUM_DOCUMENTO   ORIGEN_PLANILLA NUM_DOCUMENTO_ENCABEZADO    DIGITADO
8220568059                 2           8220568059               0
8220681644                 2                                    0
940723593097           1                                    0

第一条记录的列DIGITADO应为“1”。

Oracle 无法正确评估此“案例”:

case    
    when  x.num_documento_encabezado > '0' and x.origen_planilla = 2  then 
          1 
    else 
          0
end digitado

我尝试了不同的东西,例如,如果我为此更改以前的代码:

case    
    when  length(x.num_documento_encabezado||x.origen_planilla) > 1  then 
          1 
    else 
          0
end digitado

这是结果:

NUM_DOCUMENTO   ORIGEN_PLANILLA NUM_DOCUMENTO_ENCABEZADO    DIGITADO
8220568059                 2            8220568059              1
8220681644                 2                                    0
940723593097           1                                    0

它适用于每条记录,但这不是重点,重点是 oracle 无法评估“AND”表达式,并且原始查询比显示的示例要长得多。

现在,另一个例外是,当我只为正常的记录执行查询时,我的意思是

and     a.num_documento     in  ('8220568059')

case 句中的“AND”表达式与原始“CASE”正常工作。

结果:

NUM_DOCUMENTO   ORIGEN_PLANILLA NUM_DOCUMENTO_ENCABEZADO    DIGITADO
8220568059                 2             8220568059             1

另一件事是,这就是我认为问题所在,当第二个子查询中没有外连接时,查询运行正常,但我需要外连接,我说的是这个:

where   f.num_documento(+) = h.num_documento
and     g.num_documento(+) =f.num_division

我真的不想重写完整的查询,有人知道为什么会这样吗?


创建和插入语句,这些语句重现了问题

create table tmp_origin
(
    doc varchar2(30),
    val number,
    obs varchar2(30)
);

create table tmp_uni
(
    doc varchar2(30),
    doc_origin varchar2(30)
);

create table tmp_div
(
    doc varchar2(30),
    doc_div  varchar2(30)
);

insert into tmp_origin values ('8220568059',100000, 'NORMAL');

insert into tmp_origin values ('8220681644',200000, 'NORMAL');

insert into tmp_origin values ('940723593097',300000, 'SGP');

commit;

insert into tmp_uni values ('8220568059','8220568059');

commit;

这是上面几行适配的查询,我还加了一些其他的case,大家可以对比下判断第一个不行

select  x.num_documento,
        x.origen_planilla,
        x.num_documento_encabezado,
        case    
                when  x.num_documento_encabezado  is not null and x.origen_planilla = 2  then 
                    1 
                else 
                    0
        end digitado,
        case    
                when  length(x.num_documento_encabezado||x.origen_planilla) > 1  then 
                    1 
                else 
                    0
        end digitado2,
        case    
                when  x.origen_planilla = 2 then
                    case 
                        when x.num_documento_encabezado  is not null then 
                            1 
                        else 
                            0
                    end 
                else 
                    0
        end digitado3
from    (
            select  h.num_documento,
                    h.num_documento_encabezado,
                    h.origen_planilla
            from    (
                        select  a.doc num_documento,
                                b.doc num_documento_encabezado,
                                case when NVl(UPPER(a.obs),'X') like '%SGP%' THEN 1 ELSE 2 END origen_planilla
                        from    tmp_origin               a,
                                tmp_uni     b
                        where   a.doc     in  ( '940723593097', '8220681644','8220568059')
                        and     b.doc(+)  =   a.doc
                    ) h,
                    tmp_div f
            where   f.doc(+) = h.num_documento
            group by  h.num_documento,
                    h.num_documento_encabezado,
                    h.origen_planilla
        ) x
4

1 回答 1

1

您几乎不应该将比较运算符与 一起使用VARCHAR2,它几乎没有用处(除非您正在编写排序算法)。尤其是在您的情况下,它并没有达到您的预期。

当您比较 VARCHAR2s 时,结果将取决于字符顺序(例如'2'“大于”,'10'因为在字符表中排在后面)21

考虑:

SQL> select * from dual where '8220568059' > '0';

DUMMY
-----
X

SQL> select * from dual where '    8220568059' > '0';

DUMMY
-----

始终为正确的任务使用正确的数据类型。几乎总是只有一种数据类型可以正常工作。NUMBER处理数字时,应始终使用显式数据类型转换:

SQL> select * from dual where to_number('8220568059') > 0;

DUMMY
-----
X

此外,如果您只想知道值是否为 NULL,请使用IS NOT NULL运算符:

SQL> WITH DATA AS (
  2  SELECT '8220568059' num_documento_encabezado,
  3         2 origen_planilla FROM dual UNION ALL
  4  SELECT '', 2 FROM dual UNION ALL
  5  SELECT '', 1 FROM dual)
  6  SELECT x.origen_planilla,
  7         x.num_documento_encabezado,
  8         CASE
  9            WHEN x.num_documento_encabezado IS NOT NULL
 10             AND x.origen_planilla = 2 THEN
 11             1
 12            ELSE
 13             0
 14         END digitado
 15    FROM DATA x;

ORIGEN_PLANILLA NUM_DOCUMENTO_ENCABEZADO   DIGITADO
--------------- ------------------------ ----------
              2 8220568059                        1
              2                                   0
              1                                   0
于 2013-09-27T15:32:26.603 回答