1

I'm running this query to view data between two dates as shown in the code below, but I only get data of the current date (if dates are consecutive) or a day before if there's an interval of dates.

I mean:

  • if interval (16/05/18 - 17/05/18) only return data of 16/05/18.

  • if interval is (16/05/18 - 18/05/18) only returns data of interval (16/05/18 - 17/05/18)

Code:

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';
2
  • 1
    Why are you transforming the timestamp into a varchar before filtering? It's easier to filter using the timestamp itself. Commented May 17, 2018 at 16:02
  • '16/05/18' is a string, not a date, What data type is the column you're filtering on? The name implies it is at least a date with non-midnight imtes, but it might be an actual timestamp? Commented May 17, 2018 at 16:02

3 Answers 3

3

You are comparing your column values with string values, which means Oracle is implicitly converting the strings to dates, or timestamps, using your session NLS settings. You can see that from the execution plan's filter steps:

   1 - filter("C"."CALLTIMESTAMP">=TO_TIMESTAMP('16/05/18') AND 
              "C"."CALLTIMESTAMP"<=TO_TIMESTAMP('17/05/18'))

Those implicitly-converted values have the time component set to midnight. (They are also very fragile as they rely on the string you're using matching the session setting, which isn't always going to be under your control).

That means you are looking for values between 2018-05-16 00:00:00 and 2018-05-17 00:00:00. That will catch values at any time of day on the 16th, but will only find records on the 17th that are at exactly midnight.

The usual way to do this is with a range greater than or equal to your start date, and less than the day after your end date - which means you catch every upto but not including midnight on that day.

AND C.CALLTIMESTAMP >= timestamp '2018-05-16 00:00:00'
AND C.CALLTIMESTAMP < timestamp '2018-05-18 00:00:00'

which will find all records at any time on either the 16th or 17th.

If the column is actually a date rather than a timestamp then you can use date literals instead:

AND C.CALLTIMESTAMP >= date '2018-05-16'
AND C.CALLTIMESTAMP < date '2018-05-18';

If you don't want to use literals you can use to_date() or to_timestamp(), using a suitable explicit format mask. I'd recommend you use full four-digit years anyway, rather than 2-digit, which can still cause confusion (particularly with implicit conversion, but easy to get wrong explicitly too...)

Sign up to request clarification or add additional context in comments.

Comments

0

I recommend to you that use BETWEEN sentence C.CALLTIMESTAMP BETWEEN '16/05/18' AND '17/05/18';

I hope helped you.

1 Comment

There is no logical difference - between is handled internally as >= and <= anyway, as you can see on an execution plan.
0

Thank you all, I took the easy way

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';

2 Comments

Why rely on implicit conversion that you know can break when someone else runs this (or you run it in a different session)? You're also potentially missing any calls in the last second of the final day - e.g. at 11:59:59.321. It's much safer to use >= and < than between (or >= and <=, which is equivalent). And much, much, safer to use the correct datatype...
@AlexPoole No, I currently have the query parameterized by JAVA for a web of reports, I will take your advice to use >= and < to not miss a call.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.