Store day and date in same column in oracle - sql

I have a situation where I need to store day and date(just a date) in single column in Oracle as below:
Column name
Monday
Tuesday
25
10
But I don't like combining string and number in single column. So I want any formula or design where each of these values gets unique identifier and store like below:
Column name
1 - - - - - refers to Monday
2............refers Tuesday
3-----------refers to a actual date 1
Above is an imaginary values just for understanding.
What I need is if have to get all entries with value Monday I should apply some formula and get a number which I should use in select query
Same way if I want to select entries with date =25 then I have to apply same formula and get unique number that represents date 25 and use it in my query

Store only the DATE in a column, the day of week is derived from that.
so:
CREATE TABLE junk
(
id number,
my_date date
);
insert into junk values ( 123, sysdate );
insert into junk values ( 234, add_months(sysdate,-123) );
commit;
select my_date "The actual date",
to_char(my_date,'Day') "The day of the week",
to_char(my_date,'Dy') "other way",
to_char(my_date,'D') "another way"
from junk;
The actual date The day o oth a
-------------------- --------- --- -
27-mar-2019 15:28:15 Wednesday Wed 4
27-dec-2008 15:28:15 Saturday Sat 7
2 rows selected.
Trying to do anything more than that, you will likely only hurt yourself in the long run (consider how you will maintain things if something is updated .. consider what happens if/when somebody "accidentally" updates 1 of the values, without updating the matching one? ... because they didn't understand it ... )
-- only pull records on Wednesday
select *
from junk
where to_char(my_date,'D') = 4
/
ID MY_DATE
---------- --------------------
123 27-mar-2019 15:28:15
1 row selected.

You can use the to_char() function in oracle:
SELECT TO_CHAR(date '2019-03-27', 'DAY') day FROM dual;
Which will return the day of the week.

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

Get the number of the weekday from each date in a date list

DB-Fiddle
CREATE TABLE dates (
date_list DATE
);
INSERT INTO dates
(date_list)
VALUES
('2020-01-29'),
('2020-01-30'),
('2020-01-31'),
('2020-02-01'),
('2020-02-02');
Expected Results:
Weekday
2
3
4
5
6
I want go get the number of the weekday for each date in the table dates.
Therefore, I tried to go with the solution from this question but could not make it work:
SELECT
EXTRACT(DOW FROM DATE d.date_list))
FROM dates d
How do I need to modify the query to get the expected result?
Get rid of the date keyword it is only needed to introduce a DATE constant. If you already have a DATE value (which your column is) it's not needed:
select extract(dow from d.date_list)
from dates d

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

Oracle SQL Query to check valid date range for an activity?

I have a table called as Activity with columns like activity_id and activity_date.
Consider a data in activity table like below,
activity_id activity_date
1 1st June
2 1st July
3 1st August
4 1st September
5 1st October
Now I want to change the date of the activity 3, but I can not change the date to less than 1st July or more than 1st September as there are already some other activities on those dates.
The only valid dates for activity 3 are between 2nd July to 30th August.
Similarly, for activity 1, valid new date can be any date before 1st July.
Similarly, for activity 5, valid new date ranges from 2nd September to any date in future as its last activity.
I need to give the validation message to the user in front end if the new date is not within the range.
Input to the query will be activity id and the new activity date.
Below is the DDL script
CREATE TABLE "HEADCOUNT"."ACTIVITY"
( "ACTIVITY_ID" NUMBER(*,0) NOT NULL,
"ACTIVITY_DATE" DATE
);
Insert into "HEADCOUNT"."ACTIVITY" (ACTIVITY_ID,ACTIVITY_DATE) values (1,'01-06-2012');
Insert into "HEADCOUNT"."ACTIVITY" (ACTIVITY_ID,ACTIVITY_DATE) values (2,'01-07-2012');
Insert into "HEADCOUNT"."ACTIVITY" (ACTIVITY_ID,ACTIVITY_DATE) values (3,'01-08-2012');
Insert into "HEADCOUNT"."ACTIVITY" (ACTIVITY_ID,ACTIVITY_DATE) values (4,'01-09-2012');
Insert into "HEADCOUNT"."ACTIVITY" (ACTIVITY_ID,ACTIVITY_DATE) values (5,'01-10-2012');
This will find the date ranges for each row:
SELECT activity_id, activity_date
,NVL( LAG(activity_date) OVER(ORDER BY activity_id)
,TO_DATE('1900-01-01', 'YYYY-MM-DD')
) AS previous_date
,NVL( LEAD(activity_date) OVER(ORDER BY activity_id)
,TO_DATE('2100-01-01', 'YYYY-MM-DD')
) AS next_date
FROM activity
ORDER BY activity_id
Result:
ACTIVITY_ID ACTIVITY_DATE PREVIOUS_DATE NEXT_DATE
---------------------------------- ------------- ------------- ---------
1 01-JUN-12 01-JAN-00 01-JUL-12
2 01-JUL-12 01-JUN-12 01-AUG-12
3 01-AUG-12 01-JUL-12 01-SEP-12
4 01-SEP-12 01-AUG-12 01-OCT-12
5 01-OCT-12 01-SEP-12 01-JAN-00
Validation would then be for a given id:
"input date" > previous_date AND "input date" < next_date
Date ranges are based on previous and following records when ordered by activity_id. Perhaps the ordering should really be by activity_date, though. Using LAG and LEAD will allow for gaps in activity_ids as well.
Find date limits using a query like below (replace #param_id with changing activity id):
SELECT activity_id, activity_date
FROM activity
WHERE activity_id = #param_id-1
OR activity_id = #param_id+1
This query will return at most two results, but for first and last activities only one will be returned. So, you should read results in the front-end and decide what to do:
Specify beginning limit: Result with id #param_id-1 specifies beginning date limit. If no result with this id, this is first activity and no limit for begin date.
Specify ending limit: Result with id #param_id+1 specifies ending date limit. If no result with this id, this is last activity and no limit for end date.
Do or warn: If new date is within the range, perform change. Otherwise warn the user.

SQL Query which returns set of tuples that exists for a given data range

I have a table say EmployeeAbsence that has three columns: EmployeeId, LeaveReason and Date. This table records attendance of employees on a daily basis. I want to know the list of employees who took leave in last 14 days.
For example,
1 XYZ 2009-07-20
2 XYZ 2009-07-19
--
---
--
1001 XYZ 2009-07-04
In this case, my query output should return XYZ and alike because it contains entries for employees who were absent for last 14 days consecutively. I would appreciate an ORACLE query.
Your query will need two constraints
Data of leave must be less than 14 days away from current date
Employee has to appear only once if they have been on leave for several days / times during the 14 day period
For constraint (1) you need to know that subtracting date A from date B results in the number of days between those two dates.
For constraint (2) you need to group by the employees ID.
That said
SELECT EmployeeID
FROM EmployeeAbsence
WHERE Date between SYSDATE - 14 and SYSDATE
GROUP BY EmployeeId
should do the trick.
I assume that table has 1 record for each day of absence and you don't want to retrieve employees that were absent for e.g. last month but returned during last 14 days.
SELECT employeeId
FROM employeeAbsences base
WHERE date > trunc(sysdate)-15 -- we want to include one more day for HAVING clause to work with
GROUP BY employeeId
-- had 2 or more non-consecutive leaves --> at least one of them started during last 14 days
HAVING count(*) < max(date) - min(date)
-- first absence is less than 14 days ago
OR min(date) > trunc(sysdate) - 14;