How to select periods of time with empty data? - sql

I want to find out all periods with empty data, given the following table my_table:
id day
29 2017-06-05
26 2017-06-05
30 2017-06-06
30 2017-06-06
21 2017-06-06
21 2017-07-01
29 2017-07-01
30 2017-07-20
The answer would be:
Empty_start Empty_end
2017-06-07 2017-06-30
2017-07-02 2017-07-19
It's important that the number of months is considered. For example, in the first row the answer 2017-06-31 would be incorrect.
How can I write this query in Hive?

You can use lag() or lead():
select date_add(day, 1) as empty_start, date_add(next_day, -1) as empty_end
from (select day,
lead(day) over (order by day) as next_day
from t
group by day
) t
where next_day <> date_add(day, 1);

Related

selecting a date n days ago excluding weekends

I have a table with daily dates starting from 31st December 1999 up to 31st December 2050, excluding weekends.
Say given a particular date, for this example lets use 2019-03-14. I want to pick the date that was 30 days previous (the number of days needs to be flexible as it won't always be 30), ignoring weekends which in this case would be 2019-02-01.
How to do this?
I wrote the query below & it indeed lists 30 days previous to the specified date.
select top 30 Date
from DateDimension
where IsWeekend = 0 and Date <= '2019-03-14'
order by Date desc
So I thought I could use the query below to get the correct answer of 2019-02-01
;with ds as
(
select top 30 Date
from DateDimension
where IsWeekend = 0 and Date <= '2019-03-14'
)
select min(Date) from ds
However this doesn't work. It returns me the first date in my table, 1999-12-31.
2019-03-14
2019-03-13
2019-03-12
2019-03-11
2019-03-08
2019-03-07
2019-03-06
2019-03-05
2019-03-04
2019-03-01
2019-02-28
2019-02-27
2019-02-26
2019-02-25
2019-02-22
2019-02-21
2019-02-20
2019-02-19
2019-02-18
2019-02-15
2019-02-14
2019-02-13
2019-02-12
2019-02-11
2019-02-08
2019-02-07
2019-02-06
2019-02-05
2019-02-04
2019-02-01
TOP is meaningless without an ORDER BY, so you could do something like
;with ds as
(
select top 30 Date
from DateDimension
where IsWeekend = 0 and Date <= '2019-03-14'
order by Date DESC
)
select min(Date) from ds;
even better would be to use the ANSI syntax instead of TOP:
select Date
from DateDimension
where IsWeekend = 0 and Date <= '2019-03-14'
order by Date DESC
OFFSET 30 ROWS FETCH NEXT 1 ROW ONLY;
DISCLAIMER - code not tested since you did not provide DDL and sample data
HTH

How to find first Thursday of a month using Oracle SQL?

How to find First Thursday of this month using oracle?
select trunc(sysdate, 'MM')firstday from dual;
above is getting firstday of this month
Try with the below SQL
SELECT NEXT_DAY(TRUNC(SYSDATE, 'MONTH'),'THURSDAY') FROM DUAL;
SQL Fiddle
If you just get the next Thursday after the first day of the month, the after part means that if the 1st is itself a Thursday you will acually get a date a week too late. For instance, 2018-02-01 was a Thursday, and putting that into next_day() gives you 2018-02-08.
You need to get the next Thursday after the last day of the previous month:
next_day(trunc(sysdate, 'MM') - 1, 'THU')
Demo of both values; look at February, March and November in particular:
with t (dt) as (
select add_months(date '2018-01-15' , level - 1) from dual connect by level <= 12
)
select next_day(trunc(dt, 'MM'), 'THU') as wrong,
next_day(trunc(dt, 'MM') - 1, 'THU') as ok
from t;
WRONG OK
---------- ----------
2018-01-04 2018-01-04
2018-02-08 2018-02-01
2018-03-08 2018-03-01
2018-04-05 2018-04-05
2018-05-03 2018-05-03
2018-06-07 2018-06-07
2018-07-05 2018-07-05
2018-08-02 2018-08-02
2018-09-06 2018-09-06
2018-10-04 2018-10-04
2018-11-08 2018-11-01
2018-12-06 2018-12-06

SQL SELECT Difference between two days greater than 1 day

I have table T1
ID SCHEDULESTART SCHEDULEFINISH
1 2018-05-12 14:00:00 2018-05-14 11:00:00
2 2018-05-30 14:00:00 2018-06-01 11:00:00
3 2018-02-28 14:00:00 2018-03-02 11:00:00
4 2018-02-28 14:00:00 2018-03-01 11:00:00
5 2018-05-30 14:00:00 2018-05-31 11:00:00
I want to select all rows where difference in days (it's not important difference in hours) is greater than 1 day.
If SCHEDULESTART or SCHEDULEFINISH are on the same day or SCHEDULEFINISH is on next day then these rows should NOT be selected.
So the result should return rows with IDs: 1 2 3
because first row have difference in two days, second row (1st June is 2 days after 30th May ) and 3rd row (2nd March is 2 days after 28 February).
Is this possible somehow?
I know the function DAY but this will return only day number in that one month!!!
I must beging my query with
SELECT ID FROM T1 WHERE ...
Thanks in advance
In DB2, this should work:
select t1.*
from t1
where date(schedulestart) < date(schedulefinish) - 1 day;

SQL Partition Data by Date Range ignoring date gaps and weekends

Thank you in advance for your patience, and help!
I am trying to partition my data in a way that displays date ranges.
IMAGE: Data Set - Current Results - Desired Results
In the image you can see what my data set looks like. The results I'm currently getting. As well as, the results I would like to get.
Here is the code that I've got that is getting me my current results. I'm struggling understanding PARTITION.
Edit I can bring Saturday and Sunday back in, if the data is necessary to have all 365 consecutive days. I'm simply removing it from the Data Source in the WHERE clause.
--DELETE TEMP TABLE USED TO STORE CONSECUTIVE ABSENCES
DROP TABLE IF EXISTS #StuConsecAtt;
--CREATE TEMP TABLE THAT STORES CONSECUTIVE ABSENCE DATE RANGES
CREATE TABLE #StuConsecAtt(
SIS_NUMBER INT,
ABS_FROM DATE,
ABS_TO DATE
);
--INSERT CONSECUTIVE ABSENCE DATA NEW TABLE
WITH stuAtt
AS (
SELECT *
,DATEADD(DAY, - ROW_NUMBER() OVER (
PARTITION BY SIS_NUMBER ORDER BY ABS_DATE
), ABS_DATE) AS grp
FROM #stuCalAtt
)
INSERT INTO #StuConsecAtt
(ABS_FROM, ABS_TO, SIS_NUMBER)
SELECT min(ABS_DATE) AS [From]
,max(ABS_DATE) AS [To]
-- ,[ABS_REASON]
,SIS_NUMBER
FROM stuATT
GROUP BY SIS_NUMBER
,grp
ORDER BY [From];
SELECT * FROM #StuConsecAtt
WHERE ABS_TO > ABS_FROM;
EDIT BELOW
DATA
Looking at the data I'm trying to put consecutive days with ABSENT_DATE = Y in a single group. Below 10/4 through 10/11 are consecutive (but the weekends would be ABSENT_DAY = N) so I removed the weekends. No because 10/4 through 10/11 are grouped together (consecutive in the dataset), all with ABSENT_DAY = Y, I would like to group them so I can get the outcome range of 10/4-10/11. Just like the following range would be 10/18 - 10/19. Where the weekend gap is, is cause the issue.
SIS_NUMBER CALENDAR_DATE WEEK_DAY ABS_DATE SCHOOL_DAY ABSENT_DAY
641861 2017-10-03 Tuesday NULL Y N
641861 2017-10-04 Wednesday 2017-10-04 Y Y
641861 2017-10-05 Thursday 2017-10-05 Y Y
641861 2017-10-06 Friday 2017-10-06 Y Y
641861 2017-10-09 Monday 2017-10-09 Y Y
641861 2017-10-10 Tuesday 2017-10-10 Y Y
641861 2017-10-11 Wednesday 2017-10-11 Y Y
641861 2017-10-12 Thursday NULL N N
641861 2017-10-13 Friday NULL N N
641861 2017-10-16 Monday NULL Y N
641861 2017-10-17 Tuesday NULL Y N
641861 2017-10-18 Wednesday 2017-10-18 Y Y
641861 2017-10-19 Thursday 2017-10-19 Y Y
CURRENT RESULTS
SIS_NUMBER FROM_DATE TO_DATE
641861 2017-10-04 2017-10-06
641861 2017-10-09 2017-10-11
641861 2017-10-18 2017-10-19
DESIRED RESULTS
SIS_NUMBER FROM_DATE TO_DATE
641861 2017-10-04 2017-10-11
641861 2017-10-18 2017-10-19

Compare values for consecutive dates of same month

I have a table
ID Value Date
1 10 2017-10-02 02:50:04.480
2 20 2017-10-01 07:28:53.593
3 30 2017-09-30 23:59:59.000
4 40 2017-09-30 23:59:59.000
5 50 2017-09-30 02:36:07.520
I compare Value with previous date. But, I don't need compare result between first day in current month and last day in previous month. For this table, I don't need to compare result between 2017-10-01 07:28:53.593 and 2017-09-30 23:59:59.000 How it can be done?
Result table for this example:
ID Value Date Diff
1 10 2017-10-02 02:50:04.480 10
2 20 2017-10-01 07:28:53.593 NULL
3 30 2017-09-30 23:59:59.000 10
4 40 2017-09-29 23:59:59.000 10
5 50 2017-09-28 02:36:07.520 NULL
You can use this.
SELECT * ,
LEAD(Value) OVER( PARTITION BY DATEPART(YEAR,[Date]), DATEPART(MONTH,[Date]) ORDER BY ID ) - Value AS Diff
FROM MyTable
ORDER BY ID
you can use a query like below
select *,
diff=LEAD(Value) OVER( PARTITION BY Month(Date),Year(Date) ORDER BY Date desc)-Value
from t
order by id asc
see working demo