SQL - Select query not displaying all dates - sql

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.

Related

Date Where Clause

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

trying to selecting rows that are between two date for a period of time

This problem is like a brain teaser....so i have two dates, start date and end date and i want to select all the rows that are active between those two dates and if the period between those dates have passed then the rows should not be selected. Please note that these dates includes time
Here is an example before the code Start date = '15-MAY-2020 08:00
AM' and End date = '16-MAY-2020 08:00 AM'
As you can see there is 24 hour period between those dates and i want
to select ALL ROWS THAT ARE BETWEEN THE START DATE AND END DATE and if
the the time becomes '16-MAY-2020 08:01 AM' then those rows should not
be displayed anymore.
Now the code
select id, title, color, start_date, end_date
from colors
where end_date >= start_date and end_date <= sysdate
Summary:
If a color is between a certain start and end then it must only be displayed during that start and end otherwise it should not be shown
It is like eating ice cream, you get the ice cream and start to eat it (start) and you eat it until its is finished (end) then you have no more ice cream
Same with the colors, it starts to show at a particular date and time and has a particular date and time when it ends after that the color does not show anymore
You are close. Both your conditions needs to reference sysdate:
select id, title, color, start_date, end_date
from colors
where start_date <= sysdate and end_date >= sysdate

How to query checking if a month is between two dates?

I'm looking for query in postgresql to check whether a month is between two dates or not.
I know how to check if a date is between two date or not. Postgres also have a function to do that.
Let's say I have a a_table with rows:
ID | start_date (timestamp) | end_date (timestamp)
1 | 2019-07-20 00:00 | 2020-03-20 00:00
2 | 2019-08-20 00:00 | 2020-08-30 00:00
I have a to return the row that include a month between the start_date and end_date.
Let's say i have a month 2019-08.
So when i count
Select count(*) from a_table
Where [some where clause]
it returns 2 rows, ID 1 and ID 2
AND when i have a month 2020-01 it only return ID 1
You can use date range for this.
It's not clear to me what should happen if the start/end date in the table only covers part of a month.
If you only want to consider the full month, use the "contains" operator
select count(*)
from the_table
where daterange(start_date::date, end_date::date, '[]') #> daterange('2019-08-01'::date, '2019-09-01'::date, '[)');
The <# is the "is contained" operator which tests if the left range (the values from the table) is contained in the right hand range (the month you want to test). The comparison is done with an "open interval", which means '2019-09-01' is excluded from it. The above would not consider rows that do not contain the full August.
If you want to include partial matches as well, use the "overlaps" operator && instead:
select count(*)
from the_table
where daterange(start_date::date, end_date::date, '[]') && daterange('2019-08-01'::date, '2019-09-01'::date, '[)');
You can use to_date() in your where clause. So that your where clause would be like this.
WHERE '2019-08' BETWEEN to_date(start_date, 'YYYY-MM') and to_date(end_date ,'YYYY-MM')
I would recommend writing this as:
WHERE end_date >= TO_DATE('2019-08', 'YYYY-MM') AND
start_date < TO_DATE('2019-08', 'YYYY-MM') + INTERVAL '1 MONTH'
That is, the period includes at least one day of the month, because it starts before the end of the month and ends after the start of the month.
In addition, this has no functions on the columns in the table. So, if an index is available on either column, then it can be used. If you define the start/end as a range, then that provides other opportunities for using indexes.

Check if a week of dates sits between two specific dates SQL ORACLE

I have two dates and want to only keep rows where a certain week falls in between those two dates. I need to run this for 67+ different weeks so I'd like to change my below code to run quicker and not have to type out the 7 days of the week each time.
SELECT * FROM MY_DATA
WHERE ('05-JUNE-2017' BETWEEN start_date AND end_date
OR '06-JUNE-2017' BETWEEN start_date AND end_date
OR '07-JUNE-2017' BETWEEN start_date AND end_date
OR '08-JUNE-2017' BETWEEN start_date AND end_date
OR '09-JUNE-2017' BETWEEN start_date AND end_date
OR '10-JUNE-2017' BETWEEN start_date AND end_date
OR '11-JUNE-2017' BETWEEN start_date AND end_date);
So, you have two date intervals. One is from input_date to input_date + 6 (note: 6, not 7; you are counting the input_date too!) and the other is from start_date to end_date. And you want to write a condition that means the two intervals overlap (have non-empty intersection).
Two intervals do not overlap if one entirely precedes the other. So, the last day of one interval must be strictly less than the first day of the other interval. This can happen in one of two ways (depending on which interval comes first). The condition would look like this:
input_date + 6 < start_date OR end_date < input_date
So, this is the negation of the condition you want. Apply the logical NOT operator to this; so the condition becomes:
input_date + 6 >= start_date AND end_date >= input_date
I think your query is equivalent to
SELECT * FROM MY_DATA WHERE ('05-JUNE-2017' BETWEEN start_date - 6 AND end_date );
where '05-JUNE-2017' is the initial day of the week you are looking for.
Now you have to do this for all the initial week days...
Is that what you are looking for?
I think you are looking for something like the following:
WITH weeks AS (SELECT TO_DATE('05-07-2017', 'DD-MM-RRRR') + LEVEL * 7 - 7 week_start
, TO_DATE('05-07-2017', 'DD-MM-RRRR') + LEVEL * 7 - 1 week_end
FROM dual
CONNECT BY LEVEL < 50)
SELECT *
FROM MY_DATA
JOIN WEEKS
ON MY_DATA.end_date >= weeks.week_start
AND MY_DATA.start_date <= weeks.week_end
The first part gets you some consecutive weeks then you join them with your data to get the desired results.

Facing issue in Hive query in generating missing dates

I have a requirement where I need to go back to previous values for a column until 1000 rows and get those previous 1000 dates for my next steps, but all those 1000 previous dates are not present for that column in the table. But I need those missing dates to get from output of the query.
When I try to run below query it is not displaying 1000 previous date values from current date.
Example: let's say only 2 dates are available for date column
date
2019-01-16
2019-01-19
I have come up with a query to get back 1000 dates but it is giving only nearest date as all previous back dates are missing
SELECT date FROM table1 t
WHERE
date >= date_sub(current_date,1000) and dt<current_date ORDER BY date LIMIT 1
If I run above query it is displaying 2019-01-16, since previous 1000 days back date are not present it is giving nearest date ,which is 2019-01-16 but I need missing dates starting from 2016-04-23 (1000th date from current date) till before current date (2019-01-18) as output of my query.
You can generate dates for required range in the subquery (see date_range subquery in the example below) and left join it with your table. If there is no record in your table on some dates, the value will be null, dates will be returned from the date_range subquery without gaps. Set start_date and end_date parameters for date_range required:
set hivevar:start_date=2016-04-23; --replace with your start_date
set hivevar:end_date=current_date; --replace with your end_date
set hive.exec.parallel=true;
set hive.auto.convert.join=true; --this enables map-join
set hive.mapjoin.smalltable.filesize=25000000; --size of table to fit in memory
with date_range as
(--this query generates date range, check it's output
select date_add ('${hivevar:start_date}',s.i) as dt
from ( select posexplode(split(space(datediff('${hivevar:end_date}','${hivevar:start_date}')),' ')) as (i,x) ) s
)
select d.dt as date,
t.your_col --some value from your table on date
from date_range d
left join table1 t on d.dt=t.date
order by d.dt --order by dates if necessary