我正在运行此查询以查看两个日期之间的数据,如下面的代码所示,但我只获取当前日期的数据(如果日期是连续的)或前一天的数据,如果有一个日期间隔。
我的意思是:
如果间隔(16/05/18 - 17/05/18)仅返回16/05/18的数据。
如果间隔为(16/05/18 - 18/05/18),则仅返回间隔数据(16/05/18 - 17/05/18)
代码:
SELECT
C.SESSIONID,
SUBSTR(C.ORIGINATINGNUMBER, INSTR(C.ORIGINATINGNUMBER, ':') + 1,
INSTR(C.ORIGINATINGNUMBER, '@') - INSTR(C.ORIGINATINGNUMBER, ':') - 1) AS Origen,
TO_CHAR(C.CALLTIMESTAMP, 'DD/MM/YYYY') AS Fecha,
TO_CHAR(C.CALLTIMESTAMP,'HH:MI') AS Hora,
C.DURATION AS Duracion_IVR,
(CASE C.ENDTYPE
WHEN 1
THEN 'IVR'
WHEN 2
THEN 'Transferida'
ELSE 'Colgada'
END) AS Estado,
A.SERVICIO,
A.OPT,
A.CONTRATO_ENVIADO,
A.RPTA_WS_C,
A.RPTA_WS_L,
A.DESCRIPTIVO
FROM
CDR C
JOIN
(SELECT DISTINCT(D.SESSIONID) AS ID,
NVL(
(SELECT B.MESSAGE
FROM VPAPPLOG B
WHERE D.SESSIONID = B.SESSIONID
AND B.ACTIVITYNAME = 'CAMP'
),' ') AS SERVICIO,
NVL(
(SELECT B.ACTIVITYNAME
FROM VPAPPLOG B
WHERE D.SESSIONID = B.SESSIONID
AND B.MESSAGE = 'OPC_MENU'
),' ') AS OPT,
NVL(
(SELECT B.VARVALUE
FROM VPAPPLOG B
WHERE D.SESSIONID = B.SESSIONID
AND B.VARNAME = 'CONT_ENV'
),' ') AS CONTRATO_ENVIADO,
NVL(
(SELECT B.VARVALUE
FROM VPAPPLOG B
WHERE D.SESSIONID = B.SESSIONID
AND B.VARNAME = 'COD_RSLT_OPER'
AND B.ACTIVITYNAME = '000'
),' ') AS RPTA_WS_C,
NVL(
(SELECT B.VARVALUE
FROM VPAPPLOG B
WHERE D.SESSIONID = B.SESSIONID
AND B.VARNAME = 'COD_RSLT_OPER'
AND B.ACTIVITYNAME = '001'
),' ') AS RPTA_WS_L,
NVL(
(SELECT B.VARVALUE
FROM VPAPPLOG B
WHERE D.SESSIONID = B.SESSIONID
AND B.ACTIVITYNAME = 'MSG_RPTA'
),' ') AS DESCRIPTIVO
FROM VPAPPLOG D
) A
ON A.ID = C.SESSIONID
WHERE C.APPLICATIONNAME = 'IVR_AGBAR_Dllo'
AND C.CALLTIMESTAMP >= '16/05/18' AND C.CALLTIMESTAMP <= '17/05/18';
答案 0 :(得分:2)
您正在将列值与字符串值进行比较,这意味着Oracle使用会话NLS设置将字符串隐式转换为日期或时间戳。您可以从执行计划的过滤步骤中看到:
1 - filter("C"."CALLTIMESTAMP">=TO_TIMESTAMP('16/05/18') AND
"C"."CALLTIMESTAMP"<=TO_TIMESTAMP('17/05/18'))
这些隐式转换的值将时间组件设置为午夜。 (它们也非常脆弱,因为它们依赖于您使用的匹配会话设置的字符串,并不总是在您的控制之下。)
这意味着您正在寻找2018-05-16 00:00:00和2018-05-17 00:00:00之间的值。这将在16日的任何时间捕获值,但只会在17日找到正好在午夜的记录。
执行此操作的常用方法是使用大于或等于开始日期的范围,小于 结束日期之后的日期 - 这意味着您抓住了每一天,但不包括当天的午夜。
AND C.CALLTIMESTAMP >= timestamp '2018-05-16 00:00:00'
AND C.CALLTIMESTAMP < timestamp '2018-05-18 00:00:00'
可以在16日或17日随时查找所有记录。
如果列实际上是日期而不是时间戳,那么您可以改为使用日期文字:
AND C.CALLTIMESTAMP >= date '2018-05-16'
AND C.CALLTIMESTAMP < date '2018-05-18';
如果您不想使用文字,可以使用to_date()
或to_timestamp()
,使用合适的显式格式掩码。我建议你使用完整的四位数年份,而不是2位数,这仍然会引起混淆(特别是隐式转换,但也很容易明白错误......)
答案 1 :(得分:0)
我建议您使用BETWEEN句子 C.CALLTIMESTAMP BETWEEN&#39; 16/05/18&#39;和&#39; 17/05/18&#39;;
我希望能帮到你。
答案 2 :(得分:0)
谢谢大家,我采取了轻松的方式
SELECT C.SESSIONID,
SUBSTR(C.ORIGINATINGNUMBER,INSTR(C.ORIGINATINGNUMBER, ':') + 1,INSTR(C.ORIGINATINGNUMBER, '@') - INSTR(C.ORIGINATINGNUMBER, ':') - 1) AS Origen,
TO_CHAR(C.CALLTIMESTAMP,'DD/MM/YYYY') AS Fecha,
TO_CHAR(C.CALLTIMESTAMP,'HH:MI') AS Hora,
C.DURATION AS Duracion_IVR,
(
CASE C.ENDTYPE
WHEN 1
THEN 'IVR'
WHEN 2
THEN 'Transferida'
ELSE 'Colgada'
END) AS Estado,
A.SERVICIO,
A.OPT,
A.CONTRATO_ENVIADO,
A.RPTA_WS_C,
A.RPTA_WS_L,
A.DESCRIPTIVO
FROM CDR C
JOIN
(SELECT DISTINCT(D.SESSIONID) AS ID,
NVL(
(SELECT B.MESSAGE
FROM VPAPPLOG B
WHERE D.SESSIONID = B.SESSIONID
AND B.ACTIVITYNAME = 'CAMP'
),' ') AS SERVICIO,
NVL(
(SELECT B.ACTIVITYNAME
FROM VPAPPLOG B
WHERE D.SESSIONID = B.SESSIONID
AND B.MESSAGE = 'OPC_MENU'
),' ') AS OPT,
NVL(
(SELECT B.VARVALUE
FROM VPAPPLOG B
WHERE D.SESSIONID = B.SESSIONID
AND B.VARNAME = 'CONT_ENV'
),' ') AS CONTRATO_ENVIADO,
NVL(
(SELECT B.VARVALUE
FROM VPAPPLOG B
WHERE D.SESSIONID = B.SESSIONID
AND B.VARNAME = 'COD_RSLT_OPER'
AND B.ACTIVITYNAME = '000'
),' ') AS RPTA_WS_C,
NVL(
(SELECT B.VARVALUE
FROM VPAPPLOG B
WHERE D.SESSIONID = B.SESSIONID
AND B.VARNAME = 'COD_RSLT_OPER'
AND B.ACTIVITYNAME = '001'
),' ') AS RPTA_WS_L,
NVL(
(SELECT B.VARVALUE
FROM VPAPPLOG B
WHERE D.SESSIONID = B.SESSIONID
AND B.ACTIVITYNAME = 'MSG_RPTA'
),' ') AS DESCRIPTIVO
FROM VPAPPLOG D
) A
ON A.ID = C.SESSIONID
WHERE C.APPLICATIONNAME = 'IVR_AGBAR_Dllo'
AND C.CALLTIMESTAMP BETWEEN '16/05/18' AND '17/05/18 11:59:59,000000000 PM';