Home > Enterprise >  sql query to get data between two dates
sql query to get data between two dates

Time:02-23

I have a table comp_sal-

  PERSON_NUMBER         DATE_FROM                 DATE_TO                   DATE_COMP              SALARY_AMOUNT
    12                      01-06-2019              25-09-2021                  22-02-2020              24.38
    12                      16-07-2018              31-05-2019                  22-02-2020              23.5

I have created a query to get the salary for 2 years back from a table,comp_sal -

select * from 
(
select person_number,
salary_amount,
 to_char(date_from,'dd-mm-yyyy') date_From ,
to_char(date_to,'dd-mm-yyyy') date_to,
 ((Select to_char(sysdate,'dd-mm-')||To_char(Add_months(SYSDATE, -24), 'yyyy') from dual)) date_comp
 
 from comp_sal
 )
  where Date_comp between DATE_fROM and date_to

But I am getting the both rows as above and not just the first row because 22-02-2020 is between 01-06-2019 and 25-09-2021. I am also getting 16-07-2018 and 31-05-2019 row in the output even after adding Date_comp between DATE_fROM and date_to condition

CodePudding user response:

You didn't answer what I asked as a comment, so - here's a demo. I suspect you actually stored dates as strings and get wrong result:

SQL> with comp_sal (person_number, date_from, date_To, date_comp, salary_amount) as
  2    (select '12', '01-06-2019', '25-09-2021', '22-02-2020', 24.38 from dual union all
  3     select '12', '16-07-2018', '31-05-2019', '22-02-2020', 23.5  from dual
  4    )
  5  select *
  6  from comp_sal
  7  where date_comp between date_from and date_to;

PE DATE_FROM  DATE_TO    DATE_COMP  SALARY_AMOUNT
-- ---------- ---------- ---------- -------------
12 01-06-2019 25-09-2021 22-02-2020         24,38
12 16-07-2018 31-05-2019 22-02-2020          23,5

SQL>

If you convert strings to dates - using the TO_DATE function with appropriate format mask - then you get correct result:

SQL> with comp_sal (person_number, date_from, date_To, date_comp, salary_amount) as
  2    (select '12', '01-06-2019', '25-09-2021', '22-02-2020', 24.38 from dual union all
  3     select '12', '16-07-2018', '31-05-2019', '22-02-2020', 23.5  from dual
  4    )
  5  select *
  6  from comp_sal
  7  where to_date(date_comp, 'dd-mm-yyyy') between to_date(date_from, 'dd-mm-yyyy')
  8                                             and to_date(date_to, 'dd-mm-yyyy');

PE DATE_FROM  DATE_TO    DATE_COMP  SALARY_AMOUNT
-- ---------- ---------- ---------- -------------
12 01-06-2019 25-09-2021 22-02-2020         24,38

SQL>

CodePudding user response:

Even if you have (correctly) defined your columns as dates, your query will get that result because you are using a subquery that converts them to strings and then compares those.

If you leave everything as dates int he subquery and convert to strings only at the last moment in the outer query, for display only:

select person_number,
  to_char(date_from, 'dd-mm-yyyy') as date_from,
  to_char(date_to, 'dd-mm-yyyy') as date_to,
  to_char(date_comp, 'dd-mm-yyyy') as date_comp,
  salary_amount
from (
  select person_number,
    date_from,
    date_to,
    add_months(trunc(sysdate), -24) as date_comp,
    salary_amount
  from comp_sal
)
where date_comp between date_from and date_to

... then it would only find the single row you expect.

You could also avoid the subquery against your real table, and instead get the date_comp from a separate query that's cross-joined/applied to the real table:

select person_number,
  to_char(cs.date_from, 'dd-mm-yyyy') as date_from,
  to_char(cs.date_to, 'dd-mm-yyyy') as date_to,
  to_char(t.date_comp, 'dd-mm-yyyy') as date_comp,
  salary_amount
from comp_sal cs
cross apply (select add_months(trunc(sysdate), -24) as date_comp from dual) t
where t.date_comp between cs.date_from and cs.date_to

Either way, with your sample data as dates you get the same result:

PERSON_NUMBER DATE_FROM DATE_TO DATE_COMP SALARY_AMOUNT
12 01-06-2019 25-09-2021 22-02-2020 24.38

db<>fiddle

  • Related