Date Where Clause - sql

I need some help writing a where clause for a date field.
In my dataset, i have a date from and date to column which shows the absence from date and to date.
I need a where clause where if i search for a particular month, the results would show if the absence falls outwith the date parameter.
e.g absent from 01/08/2021 until 11/11/2021, and i run the report from 01/10/2021 - 31/10/2021, the results should show the persons record as they were absent for the month of Oct
TIA

Assuming that the ranges are inclusive and you want to enclude the entirety of the day in the range then you can use:
SELECT *
FROM absences
WHERE date_from < DATE '2021-10-31' + INTERVAL '1' DAY
AND date_to >= DATE '2021-10-01'
Note: If you are only storing dates at midnight then you can use date_from <= DATE '2021-10-31' but if you are storing dates with a non-midnight time component and want to include the entirety of the final day then you need to use < and add a day.
Which, for the sample data:
CREATE TABLE absences (date_from, date_to) AS
SELECT DATE '2021-08-01', DATE '2021-11-11' FROM DUAL;
Outputs:
DATE_FROM
DATE_TO
2021-08-01 00:00:00
2021-11-11 00:00:00
db<>fiddle here

Related

Compare date filed with month and year in Postgres

I have a date field in one of my tables and the column name is from_dt. Now I have to compare a month and year combination against this from_dt field and check whether the month has already passed. The current database function uses separate conditions for the month and the year, but this is wrong as it will compare month and year separately. The current code is like this
SELECT bill_rate, currency FROM table_name WHERE
emp_id = employee_id_param
AND EXTRACT(MONTH FROM from_dt) <= month_param
AND EXTRACT(YEAR FROM from_dt) <= year_param
Now the fromt_dt field has value 2021-10-11. If I give month_param as 01 and year_param as 2022, this condition will not work as the month 10 is greater than 1, which I have given. Basically, I need to check whether 01-2022 (Jan 2022) is greater than r equal to 2021-10-01(October 1st, 2021). It would be very much helpful if someone can shed some light here.
If you just want to check whether one date is >= then another:
# select '2022-01-01'::date >= '2021-10-11'::date;
?column?
----------
t
If you want to restrict to year/month then:
select date_trunc('month','2022-01-01'::date) >= date_trunc('month', '2021-10-11'::date);
?column?
----------
t
Where the date_trunc components are:
select date_trunc('month','2022-01-01'::date) ;
date_trunc
------------------------
2022-01-01 00:00:00-08
select date_trunc('month','2021-10-11'::date) ;
date_trunc
------------------------
2021-10-01 00:00:00-07
See Postgres date_trunc for more information.
Assuming the given year_param and month_param are integers you can use the make_date function to create the first of the year_month and date_trunc to get the first on the month from the table. Just compare those values. (See date functions) So:
select bill_rate, currency
from table_name
where emp_id = employee_id_param
and date_trunc('month',from_dt) =
make_date( year_param, month_param, 01);

SQL - Select query not displaying all dates

I have a table that has a start date, an end date, and the pay period information according to the start and end dates. When I try to find the pay period information with a date range, the very first pay period information does not show in the result.
For example, when I run the following query:
select *
FROM PayPeriod
where start_date between '2020-12-01' and '2020-12-21'
I should see the following result:
Start_date End_date Pay_perild
2020-11-22 2020-12-05 2020-12-wk1
2020-12-06 2020-12-19 2020-12-wk3
2020-12-20 2021-01-02 2021-01-wk1
Instead, I get:
Start_date End_date Pay_period
2020-12-06 2020-12-19 2020-12-wk3
2020-12-20 2021-01-02 2021-01-wk1
The date range and the pay period that includes '2020-12-01' is omitted. Why isn't it showing, and how do I correct this?
Looks like I've got what you wanted. You need to intersect two time intervals.
To find intersecting intervals of two tables (say TableA and TableB, I use tables as more general case to distinguish two intervals by their meaning/role/whatever) you need to compare begin date of one table with end date of another for both tables (putting each of them to "one" and "another" role):
TableA.start_date < TableB.end_date
and TableB.start_date < TableA.end_date
It is the rule for the case where your intervals are continuous, e.g. end_date of one period is "just before" (like real numbers) of the start_dare of another (so all items in the interval will have start_date <= item_date < end_date). For discrete intervals (like days, where duration of one day will have identical values of start_date and end_date) there would be <= in intersection condition.
So, your query will look like
DECLARE #period_from date = CONVERT ('2020-12-01' 23),
#period_to date = CONVERT ('2020-12-21', 23);
select *
FROM PayPeriod
where start_date < #period_to /*or <= depending on inclusion of end_date*/
and #period_from < end_date /*or <= depending on inclusion of end_date*/
The query is returning the result as you instructed. It's working perfectly. In your query you put the date range condition one the start_date:
where start_date between '2020-12-01' and '2020-12-21'
The first row that you expect has start_date = 2020-11-22. This date is not in the rage you specified in the condition.
If you want the first row in the result set simply you need to change the condition.
If you have to put condition on the start date you have to make the date range wider in the condition. For example:
SELECT *
FROM PayPeriod
WHERE start_date between '2020-11-21' and '2020-12-21'
Based on your application requirement you have to arrange the condition.

Calculate Week Numbers based on the initial given date to end date

I have below scenario that Business want to calculate Week Number based on Given Start Date to End Date.
For Ex: Start Date = 8/24/2020 End Date = 12/31/2020 ( These Start date & end date are not constant they may change from year to year )
Expected Output below:
[Date 1 Date 2 Week Number
8/24/2020 8/30/2020 week1
8/31/2020 9/6/2020 week2
9/7/2020 9/14/2020 week3
9/15/2020 9/21/2020 week4
9/22/2020 9/28/2020 week5
9/29/2020 10/5/2020 week6
10/6/2020 10/12/2020 week7
10/13/2020 10/19/2020 week8
10/20/2020 10/26/2020 week9
10/27/2020 11/02/2020 week10
11/03/2020 11/09/2020 week11
11/10/2020 11/16/2020 week12
11/17/2020 11/23/2020 week13
11/24/2020 11/30/2020 week14
I need Oracle Query to calculate Week Number(s) like above .. Based on Start date for 7 days then week number will be calcuated.. But remember that crossing months some month have 30 days and some month 31 days etc.. How to calculate ? Appreciate your help!!
Seems your looking for custom week definition rather that built-ins. But not overly difficult. The first thing is to convert from strings to dates (if columns actually coming off table this conversion is not required), and from there let Oracle do all the calculations as you can apply arithmetic operations to dates, except adding 2 dates. Oracle will automatically handle differing number of days per month correctly.
Two methods for this request:
Use a recursive CTE (with)
with dates(start_date,end_date) as
( select date '2020-08-24' start_date
, date '2020-12-31' end_date
from dual
)
, weeks (wk, wk_start, wk_end, e_date) as
( select 1, start_date, start_date+6 ld, end_date from dates
union all
select wk+1, wk_end+1, wk_end+7, e_date
from weeks
where wk_end<e_date
)
select wk, wk_start, wk_end from weeks;
Use Oracle connect by
with dates(start_date,end_date) as
( select date '2020-08-24' start_date
, date '2020-12-31' end_date
from dual
)
select level wk
, start_date+7*(level-1) wk_start
, start_date+6+7*(level-1)
from dates
connect by level <= ceil( (end_date-start_date)/7.0);
Depend on how strict you need to be with the end date specified you may need to adjust the last row returned. Both queries do not make adjust for that. They just ensure no week begins after that date. But the last week contains the full 7 days, which may end after the specified end date.
If your date datatype is varchar then first convert it to date and then convert it back to varchar.
convert date to to_char(to_date('8/24/2020','MM/DD/YYYY'),'WW')
If you to keep week datatype as a number then you can do something like this
to_number(to_char(to_date('8/24/2020','MM/DD/YYYY'),'WW'))
Few options according to your need.
WW Week of year (1-53) where week 1 starts on the first day of the year and continues to the seventh day of the year.
W Week of month (1-5) where week 1 starts on the first day of the month and ends on the seventh.
IW Week of year (1-52 or 1-53) based on the ISO standard.

ORA-01839: date not valid for month specified

The following query returns
select to_char( trunc(sysdate) - numtoyminterval(level - 1, 'month'), 'mon-yy') as month from dual connect by level <= 12
last 12 months according to today's date(i.e. 2-Jan-18).
Say if today's date is 29-DEC-17 it gives oracle sql error:
ORA-01839: date not valid for month specified
(since on subtracting there would be a date in the result as '29-FEB-17' which is not possible). So on specific dates this error would pop-up. How do you suggest to overcome this?
I prefer ADD_MONTHS (TRUNC of a date literal is stupid, but I left it as you'd have SYSDATE anyway, wouldn't you?):
SQL> select to_char(add_months(trunc(date '2017-12-29'), -level), 'dd-mon-yy',
2 'nls_Date_language = english') as month
3 from dual
4 connect by level <= 12;
MONTH
------------------
29-nov-17
29-oct-17
29-sep-17
29-aug-17
29-jul-17
29-jun-17
29-may-17
29-apr-17
29-mar-17
28-feb-17
29-jan-17
29-dec-16
12 rows selected.
SQL>
This behavior of INTERVAL YEAR TO MONTH is as documented, see Datetime/Interval Arithmetic
You should consider function ADD_MONTHS:
If date is the last day of the month or if the resulting month has
fewer days than the day component of date, then the result is the last
day of the resulting month. Otherwise, the result has the same day
component as date.
It depends on your requirements what you consider as "right". In fact "one month" does not have a fixed duration.

Oracle sql. finding last quarter's last date for given number of dates

I need to find the last quarter's last date and insert into another column for dates from present in a column. i.e read from the same table and insert into another column
EX
column 1 | column 2
02-aug-16|30-jun-16
05-dec-16|30-sep-16
Assuming you know how to insert a value in a column, and also assuming - if your date is not in the correct date datatype but instead is a string, then you know how to change it to a date with to_date() ...
the only remaining question is, given a date, how do you find the last date of the previous quarter.
trunc() can used with a date parameter. The function truncates the input date. You can give it a second argument to show what to truncate to. 'q' is for quarter. So trunc(date_col, 'q') will return the first day of the "current" quarter (current to the value stored in date_col, that is). Then you can subtract 1 (which means one day) to get the last day of the previous quarter.
SQL> select sysdate as today, trunc(sysdate, 'q') - 1 as last_day_of_prev_qtr from dual;
TODAY LAST_DAY_OF_PREV_QTR
---------- --------------------
2016-08-02 2016-06-30
If I got it right, truncate the source date to a quarter start and substract one day
select col1, TRUNC(col1,'Q') - interval '1' day col2
from (
select cast('02-aug-16' as date) col1 from dual
union all
select cast('05-dec-16' as date) col1 from dual
);