Oracle SQL Developer日期区间过滤结果缺失问题求助
解决日期区间查询仅返回前一天数据的问题
你碰到的是一个非常常见的日期时间查询陷阱——你的CALLTIMESTAMP字段是包含完整时间戳的(日期+时分秒),但你在WHERE子句里使用的日期字面量只指定了日期部分,数据库会自动把这个日期解析成当天的午夜0点(比如'17/05/18'会被解读为'17/05/18 00:00:00')。这就导致所有17号当天(时间大于00:00:00)的记录都被过滤掉了,自然只能拿到区间结束日期前一天的数据;同理,区间到18号时,只能拿到17号及之前的内容。
两种可行的修复方案
方案1:明确指定结束日期的最后一秒
把结束日期的时间部分补全为23:59:59,确保覆盖当天所有时间的记录:
WHERE C.APPLICATIONNAME = 'IVR_AGBAR_Dllo' AND C.CALLTIMESTAMP >= '16/05/18 00:00:00' AND C.CALLTIMESTAMP <= '17/05/18 23:59:59';
⚠️ 注意:如果你的数据库支持毫秒级时间戳(比如Oracle的TIMESTAMP类型),这种方式可能会漏掉23:59:59.001及之后的记录,不是最严谨的方案。
方案2:使用小于号+结束日期次日(推荐)
这是更稳妥的写法,通过<操作符指向区间结束日期的次日凌晨0点,能完整包含结束日期当天的所有记录:
WHERE C.APPLICATIONNAME = 'IVR_AGBAR_Dllo' AND C.CALLTIMESTAMP >= '16/05/18' AND C.CALLTIMESTAMP < '18/05/18'; -- 原区间是16-17号,这里用18号作为上限
如果是查询16-18号的区间,就调整为:
AND C.CALLTIMESTAMP >= '16/05/18' AND C.CALLTIMESTAMP < '19/05/18';
修复后的完整SQL代码
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 < '18/05/18'; -- 这里修改为区间结束日期的次日
额外建议
为了避免日期格式解析的问题,最好使用数据库自带的日期函数明确指定格式,比如Oracle的TO_DATE,防止因数据库NLS设置不同导致的解析错误:
AND C.CALLTIMESTAMP >= TO_DATE('16/05/18', 'DD/MM/YY') AND C.CALLTIMESTAMP < TO_DATE('18/05/18', 'DD/MM/YY')
内容的提问来源于stack exchange,提问作者Carlos Arbeláez
相关产品推荐
相关产品推荐

