变量没有正确比较
Variables doesn't compare properly
问题:为什么我的 decode
语句没有 return 我需要的值?
我注意到的第一件事是日期格式错误,因为蟾蜍在 DD/MM/RR
中分配它,我试图将它与 DD/MM/YYY
进行比较。所以我尝试在程序开始时设置 nls
格式。
我可以就如何解决这个问题提出建议吗?
请找到下面的代码
declare
vMES_ACTUAL NUMBER(6);
vMES_ANT NUMBER(6);
vTRIM_ANT NUMBER(6);
vTRIM_ACT NUMBER(6);
vMES_BASE NUMBER(6);
vMES_INTA NUMBER(6);
vMES_ULT_DIC NUMBER(6);
vFECHA DATE;
vMES_CURSO NUMBER(6);
----------
vFECHA1 DATE;
vFECHA2 DATE;
vFECHA3 DATE;
vFECHA4 DATE;
vFECHA5 DATE;
vFECHA6 DATE;
vNUM_DIAS_CARGA NUMBER;
vSEMANAS_TRANSC NUMBER;
var_mes1 number(6);
var_mes2 number(6);
var_mes3 number(6);
----------
FEC_VAR_DIA VARCHAR2(10);
Pmes number(6):=201810;
begin
execute immediate 'alter session set nls_date_format = ''DD/MM/YYYY''';
SELECT Pmes INTO vMES_CURSO FROM DUAL;
/* Ultimos 6 dias de carga */
SELECT MAX(ID_FECHA) INTO vFECHA1
FROM CAP_BPP_FECHA_VAR6DIAS;
SELECT NVL(MAX(ID_FECHA),vFECHA1) INTO vFECHA2
FROM CAP_BPP_FECHA_VAR6DIAS
WHERE ID_FECHA < vFECHA1;
SELECT NVL(MAX(ID_FECHA),vFECHA2) INTO vFECHA3
FROM CAP_BPP_FECHA_VAR6DIAS
WHERE ID_FECHA < vFECHA2;
SELECT NVL(MAX(ID_FECHA),vFECHA3) INTO vFECHA4
FROM CAP_BPP_FECHA_VAR6DIAS
WHERE ID_FECHA < vFECHA3;
SELECT NVL(MAX(ID_FECHA),vFECHA4) INTO vFECHA5
FROM CAP_BPP_FECHA_VAR6DIAS
WHERE ID_FECHA < vFECHA4;
SELECT NVL(MAX(ID_FECHA),vFECHA5) INTO vFECHA6
FROM CAP_BPP_FECHA_VAR6DIAS
WHERE ID_FECHA < vFECHA5;
/* Hace el conteo de los numeros de dias */
SELECT COUNT(*)
INTO vNUM_DIAS_CARGA
FROM CAP_BPP_FECHA_VAR6DIAS;
EXECUTE IMMEDIATE ('TRUNCATE TABLE CAP_BPP_CTA_VAR_PASO');
INSERT /*+ NOLOGGING */ INTO CAP_BPP_CTA_VAR6DIAS_PASO(
ID_CLIENTE, ID_CONTRATO, ID_MES, ID_PRODUCTO, ID_SUBPRODUCTO,
ID_DIVISA,
SDO_PUNT_DIA_1)
SDO_PUNT_DIA_2,
SDO_PUNT_DIA_3,
SDO_PUNT_DIA_4,
SDO_PUNT_DIA_5,
SDO_PUNT_DIA_6)
SELECT BT.ID_CLIENTE, BT.ID_CONTRATO, vMES_CURSO, BT.ID_PRODUCTO,
BT.ID_SUBPRODUCTO,BT.ID_DIVISA,
CASE WHEN vNUM_DIAS_CARGA < 1 THEN 0 ELSE NVL(SUM(DECODE(TO_DATE(BT.FECHA_INFORMACION,'DD/MM/YYYY'),vFECHA1,SDO_PUNTUAL)),0) END SDO_PUNT_DIA_1
CASE WHEN vNUM_DIAS_CARGA < 2 THEN 0 ELSE NVL(SUM(DECODE(BT.FECHA_INFORMACION,vFECHA2,SDO_PUNTUAL)),0) END SDO_PUNT_DIA_2,
CASE WHEN vNUM_DIAS_CARGA < 3 THEN 0 ELSE NVL(SUM(DECODE(BT.FECHA_INFORMACION,vFECHA3,SDO_PUNTUAL)),0) END SDO_PUNT_DIA_3,
CASE WHEN vNUM_DIAS_CARGA < 4 THEN 0 ELSE NVL(SUM(DECODE(BT.FECHA_INFORMACION,vFECHA4,SDO_PUNTUAL)),0) END SDO_PUNT_DIA_4,
CASE WHEN vNUM_DIAS_CARGA < 5 THEN 0 ELSE NVL(SUM(DECODE(BT.FECHA_INFORMACION,vFECHA5,SDO_PUNTUAL)),0) END SDO_PUNT_DIA_5,
CASE WHEN vNUM_DIAS_CARGA < 6 THEN 0 ELSE NVL(SUM(DECODE(BT.FECHA_INFORMACION,vFECHA6,SDO_PUNTUAL)),0) END SDO_PUNT_DIA_6
FROM CAP_BPP_CTA_FTE_DIA BT
WHERE BT.FECHA_INFORMACION IN (vFECHA1, vFECHA2, vFECHA3, vFECHA4, vFECHA5, vFECHA6)
GROUP BY ID_CLIENTE, ID_CONTRATO, vMES_CURSO, ID_PRODUCTO, BT.ID_SUBPRODUCTO, ID_DIVISA;)
COMMIT;
end;
您目前正在这样做:
NVL(SUM(DECODE(TO_DATE(BT.FECHA_INFORMACION,'DD/MM/YYYY'),vFECHA1,SDO_PUNTUAL)),0)
正如评论中所讨论的那样,不应将 TO_DATE()
应用于已经是日期的内容,因此您需要:
NVL(SUM(DECODE(BT.FECHA_INFORMACION,vFECHA1,SDO_PUNTUAL)),0)
正如您在进行比较时所做的那样,或者如果 FECHA_INFORMACION
的值的时间部分不是午夜:
NVL(SUM(DECODE(TRUNC(BT.FECHA_INFORMACION),vFECHA1,SDO_PUNTUAL)),0)
TRUNC()
函数默认将日期值的时间部分设置为午夜,因此一天的所有值都具有相同的日期时间值。如果 ID_FECHA
也有非午夜时间,那么您也可以截断这些变量,尽管从联系人看来不太可能是这种情况:
NVL(SUM(DECODE(TRUNC(BT.FECHA_INFORMACION),TRUNC(vFECHA1),SDO_PUNTUAL)),0)
您也可以在解码中默认为零,但在这种情况下应该没有太大区别。
如果没有 TO_DATE()
及其隐含的 TO_CHAR()
,NLS 设置无关紧要,因为您要将日期与其他日期进行比较。 Oracle 使用与您的客户端如何将日期显示为字符串几乎没有关系的内部表示。
你可能也有这个问题:
WHERE BT.FECHA_INFORMACION IN (vFECHA1, vFECHA2, vFECHA3, vFECHA4, vFECHA5, vFECHA6)
因为那也只会恰好匹配午夜。你也可以截断它:
WHERE TRUNC(BT.FECHA_INFORMACION) IN (vFECHA1, vFECHA2, vFECHA3, vFECHA4, vFECHA5, vFECHA6)
再次假设 FECHA_INFORMACION
有非午夜时间并且变量都在午夜。这将阻止使用 FECHA_INFORMACION
,但您可以改为比较多个范围。先看看是否能解决问题。
我用最简单的方法解决了这个问题,也许我的问题表述有误,因为我只想匹配日期格式以从查询中获取数据。感谢那些试图提供帮助的人。这就是我解决它的方式。
INSERT /*+ NOLOGGING */ INTO CAP_BPP_CTA_VAR6DIAS_PASO(
ID_CLIENTE, ID_CONTRATO, ID_MES, ID_PRODUCTO, ID_SUBPRODUCTO, ID_DIVISA,
SDO_PUNT_DIA_1,
SDO_PUNT_DIA_2,
SDO_PUNT_DIA_3,
SDO_PUNT_DIA_4,
SDO_PUNT_DIA_5,
SDO_PUNT_DIA_6)
SELECT /*+ PARALLEL(BT,4) */
ID_CLIENTE, ID_CONTRATO, vMES_CURSO, ID_PRODUCTO, BT.ID_SUBPRODUCTO,ID_DIVISA,
CASE WHEN vNUM_DIAS_CARGA < 1 THEN 0 ELSE SUM(DECODE(TO_DATE(BT.FECHA_INFORMACION,'DD/MM/RR'),vFECHA1,SDO_PUNTUAL)) END SDO_PUNT_DIA_1,
CASE WHEN vNUM_DIAS_CARGA < 2 THEN 0 ELSE SUM(DECODE(TO_DATE(BT.FECHA_INFORMACION,'DD/MM/RR'),vFECHA2,SDO_PUNTUAL)) END SDO_PUNT_DIA_2,
CASE WHEN vNUM_DIAS_CARGA < 3 THEN 0 ELSE SUM(DECODE(TO_DATE(BT.FECHA_INFORMACION,'DD/MM/RR'),vFECHA3,SDO_PUNTUAL)) END SDO_PUNT_DIA_3,
CASE WHEN vNUM_DIAS_CARGA < 4 THEN 0 ELSE SUM(DECODE(TO_DATE(BT.FECHA_INFORMACION,'DD/MM/RR'),vFECHA4,SDO_PUNTUAL)) END SDO_PUNT_DIA_4,
CASE WHEN vNUM_DIAS_CARGA < 5 THEN 0 ELSE SUM(DECODE(TO_DATE(BT.FECHA_INFORMACION,'DD/MM/RR'),vFECHA5,SDO_PUNTUAL)) END SDO_PUNT_DIA_5,
CASE WHEN vNUM_DIAS_CARGA < 6 THEN 0 ELSE SUM(DECODE(TO_DATE(BT.FECHA_INFORMACION,'DD/MM/RR'),vFECHA6,SDO_PUNTUAL)) END SDO_PUNT_DIA_6
FROM CAP_BPP_CTA_FTE_DIA BT
WHERE TO_DATE(BT.FECHA_INFORMACION,'DD/MM/RR') IN (vFECHA1, vFECHA2, vFECHA3, vFECHA4, vFECHA5, vFECHA6)
GROUP BY ID_CLIENTE, ID_CONTRATO, vMES_CURSO, ID_PRODUCTO, BT.ID_SUBPRODUCTO, ID_DIVISA;
COMMIT;
问题:为什么我的 decode
语句没有 return 我需要的值?
我注意到的第一件事是日期格式错误,因为蟾蜍在 DD/MM/RR
中分配它,我试图将它与 DD/MM/YYY
进行比较。所以我尝试在程序开始时设置 nls
格式。
我可以就如何解决这个问题提出建议吗?
请找到下面的代码
declare
vMES_ACTUAL NUMBER(6);
vMES_ANT NUMBER(6);
vTRIM_ANT NUMBER(6);
vTRIM_ACT NUMBER(6);
vMES_BASE NUMBER(6);
vMES_INTA NUMBER(6);
vMES_ULT_DIC NUMBER(6);
vFECHA DATE;
vMES_CURSO NUMBER(6);
----------
vFECHA1 DATE;
vFECHA2 DATE;
vFECHA3 DATE;
vFECHA4 DATE;
vFECHA5 DATE;
vFECHA6 DATE;
vNUM_DIAS_CARGA NUMBER;
vSEMANAS_TRANSC NUMBER;
var_mes1 number(6);
var_mes2 number(6);
var_mes3 number(6);
----------
FEC_VAR_DIA VARCHAR2(10);
Pmes number(6):=201810;
begin
execute immediate 'alter session set nls_date_format = ''DD/MM/YYYY''';
SELECT Pmes INTO vMES_CURSO FROM DUAL;
/* Ultimos 6 dias de carga */
SELECT MAX(ID_FECHA) INTO vFECHA1
FROM CAP_BPP_FECHA_VAR6DIAS;
SELECT NVL(MAX(ID_FECHA),vFECHA1) INTO vFECHA2
FROM CAP_BPP_FECHA_VAR6DIAS
WHERE ID_FECHA < vFECHA1;
SELECT NVL(MAX(ID_FECHA),vFECHA2) INTO vFECHA3
FROM CAP_BPP_FECHA_VAR6DIAS
WHERE ID_FECHA < vFECHA2;
SELECT NVL(MAX(ID_FECHA),vFECHA3) INTO vFECHA4
FROM CAP_BPP_FECHA_VAR6DIAS
WHERE ID_FECHA < vFECHA3;
SELECT NVL(MAX(ID_FECHA),vFECHA4) INTO vFECHA5
FROM CAP_BPP_FECHA_VAR6DIAS
WHERE ID_FECHA < vFECHA4;
SELECT NVL(MAX(ID_FECHA),vFECHA5) INTO vFECHA6
FROM CAP_BPP_FECHA_VAR6DIAS
WHERE ID_FECHA < vFECHA5;
/* Hace el conteo de los numeros de dias */
SELECT COUNT(*)
INTO vNUM_DIAS_CARGA
FROM CAP_BPP_FECHA_VAR6DIAS;
EXECUTE IMMEDIATE ('TRUNCATE TABLE CAP_BPP_CTA_VAR_PASO');
INSERT /*+ NOLOGGING */ INTO CAP_BPP_CTA_VAR6DIAS_PASO(
ID_CLIENTE, ID_CONTRATO, ID_MES, ID_PRODUCTO, ID_SUBPRODUCTO,
ID_DIVISA,
SDO_PUNT_DIA_1)
SDO_PUNT_DIA_2,
SDO_PUNT_DIA_3,
SDO_PUNT_DIA_4,
SDO_PUNT_DIA_5,
SDO_PUNT_DIA_6)
SELECT BT.ID_CLIENTE, BT.ID_CONTRATO, vMES_CURSO, BT.ID_PRODUCTO,
BT.ID_SUBPRODUCTO,BT.ID_DIVISA,
CASE WHEN vNUM_DIAS_CARGA < 1 THEN 0 ELSE NVL(SUM(DECODE(TO_DATE(BT.FECHA_INFORMACION,'DD/MM/YYYY'),vFECHA1,SDO_PUNTUAL)),0) END SDO_PUNT_DIA_1
CASE WHEN vNUM_DIAS_CARGA < 2 THEN 0 ELSE NVL(SUM(DECODE(BT.FECHA_INFORMACION,vFECHA2,SDO_PUNTUAL)),0) END SDO_PUNT_DIA_2,
CASE WHEN vNUM_DIAS_CARGA < 3 THEN 0 ELSE NVL(SUM(DECODE(BT.FECHA_INFORMACION,vFECHA3,SDO_PUNTUAL)),0) END SDO_PUNT_DIA_3,
CASE WHEN vNUM_DIAS_CARGA < 4 THEN 0 ELSE NVL(SUM(DECODE(BT.FECHA_INFORMACION,vFECHA4,SDO_PUNTUAL)),0) END SDO_PUNT_DIA_4,
CASE WHEN vNUM_DIAS_CARGA < 5 THEN 0 ELSE NVL(SUM(DECODE(BT.FECHA_INFORMACION,vFECHA5,SDO_PUNTUAL)),0) END SDO_PUNT_DIA_5,
CASE WHEN vNUM_DIAS_CARGA < 6 THEN 0 ELSE NVL(SUM(DECODE(BT.FECHA_INFORMACION,vFECHA6,SDO_PUNTUAL)),0) END SDO_PUNT_DIA_6
FROM CAP_BPP_CTA_FTE_DIA BT
WHERE BT.FECHA_INFORMACION IN (vFECHA1, vFECHA2, vFECHA3, vFECHA4, vFECHA5, vFECHA6)
GROUP BY ID_CLIENTE, ID_CONTRATO, vMES_CURSO, ID_PRODUCTO, BT.ID_SUBPRODUCTO, ID_DIVISA;)
COMMIT;
end;
您目前正在这样做:
NVL(SUM(DECODE(TO_DATE(BT.FECHA_INFORMACION,'DD/MM/YYYY'),vFECHA1,SDO_PUNTUAL)),0)
正如评论中所讨论的那样,不应将 TO_DATE()
应用于已经是日期的内容,因此您需要:
NVL(SUM(DECODE(BT.FECHA_INFORMACION,vFECHA1,SDO_PUNTUAL)),0)
正如您在进行比较时所做的那样,或者如果 FECHA_INFORMACION
的值的时间部分不是午夜:
NVL(SUM(DECODE(TRUNC(BT.FECHA_INFORMACION),vFECHA1,SDO_PUNTUAL)),0)
TRUNC()
函数默认将日期值的时间部分设置为午夜,因此一天的所有值都具有相同的日期时间值。如果 ID_FECHA
也有非午夜时间,那么您也可以截断这些变量,尽管从联系人看来不太可能是这种情况:
NVL(SUM(DECODE(TRUNC(BT.FECHA_INFORMACION),TRUNC(vFECHA1),SDO_PUNTUAL)),0)
您也可以在解码中默认为零,但在这种情况下应该没有太大区别。
如果没有 TO_DATE()
及其隐含的 TO_CHAR()
,NLS 设置无关紧要,因为您要将日期与其他日期进行比较。 Oracle 使用与您的客户端如何将日期显示为字符串几乎没有关系的内部表示。
你可能也有这个问题:
WHERE BT.FECHA_INFORMACION IN (vFECHA1, vFECHA2, vFECHA3, vFECHA4, vFECHA5, vFECHA6)
因为那也只会恰好匹配午夜。你也可以截断它:
WHERE TRUNC(BT.FECHA_INFORMACION) IN (vFECHA1, vFECHA2, vFECHA3, vFECHA4, vFECHA5, vFECHA6)
再次假设 FECHA_INFORMACION
有非午夜时间并且变量都在午夜。这将阻止使用 FECHA_INFORMACION
,但您可以改为比较多个范围。先看看是否能解决问题。
我用最简单的方法解决了这个问题,也许我的问题表述有误,因为我只想匹配日期格式以从查询中获取数据。感谢那些试图提供帮助的人。这就是我解决它的方式。
INSERT /*+ NOLOGGING */ INTO CAP_BPP_CTA_VAR6DIAS_PASO(
ID_CLIENTE, ID_CONTRATO, ID_MES, ID_PRODUCTO, ID_SUBPRODUCTO, ID_DIVISA,
SDO_PUNT_DIA_1,
SDO_PUNT_DIA_2,
SDO_PUNT_DIA_3,
SDO_PUNT_DIA_4,
SDO_PUNT_DIA_5,
SDO_PUNT_DIA_6)
SELECT /*+ PARALLEL(BT,4) */
ID_CLIENTE, ID_CONTRATO, vMES_CURSO, ID_PRODUCTO, BT.ID_SUBPRODUCTO,ID_DIVISA,
CASE WHEN vNUM_DIAS_CARGA < 1 THEN 0 ELSE SUM(DECODE(TO_DATE(BT.FECHA_INFORMACION,'DD/MM/RR'),vFECHA1,SDO_PUNTUAL)) END SDO_PUNT_DIA_1,
CASE WHEN vNUM_DIAS_CARGA < 2 THEN 0 ELSE SUM(DECODE(TO_DATE(BT.FECHA_INFORMACION,'DD/MM/RR'),vFECHA2,SDO_PUNTUAL)) END SDO_PUNT_DIA_2,
CASE WHEN vNUM_DIAS_CARGA < 3 THEN 0 ELSE SUM(DECODE(TO_DATE(BT.FECHA_INFORMACION,'DD/MM/RR'),vFECHA3,SDO_PUNTUAL)) END SDO_PUNT_DIA_3,
CASE WHEN vNUM_DIAS_CARGA < 4 THEN 0 ELSE SUM(DECODE(TO_DATE(BT.FECHA_INFORMACION,'DD/MM/RR'),vFECHA4,SDO_PUNTUAL)) END SDO_PUNT_DIA_4,
CASE WHEN vNUM_DIAS_CARGA < 5 THEN 0 ELSE SUM(DECODE(TO_DATE(BT.FECHA_INFORMACION,'DD/MM/RR'),vFECHA5,SDO_PUNTUAL)) END SDO_PUNT_DIA_5,
CASE WHEN vNUM_DIAS_CARGA < 6 THEN 0 ELSE SUM(DECODE(TO_DATE(BT.FECHA_INFORMACION,'DD/MM/RR'),vFECHA6,SDO_PUNTUAL)) END SDO_PUNT_DIA_6
FROM CAP_BPP_CTA_FTE_DIA BT
WHERE TO_DATE(BT.FECHA_INFORMACION,'DD/MM/RR') IN (vFECHA1, vFECHA2, vFECHA3, vFECHA4, vFECHA5, vFECHA6)
GROUP BY ID_CLIENTE, ID_CONTRATO, vMES_CURSO, ID_PRODUCTO, BT.ID_SUBPRODUCTO, ID_DIVISA;
COMMIT;