HIVE Obtain First Weekday of Current Month - hive

Morning,
Title says it all. I cannot for the life of me figure out how to obtain the first weekday of the current month (or previous month etc.) in HQL.
So if today's date were to be evaluated, it should return 2/3/2020 as the date, since the 3rd was the first weekday of this month.
I've tried case statements to evaluate the first day of the month, and if it is a saturday, add 2 days, a sunday, add 1 but it is not working and I receive the following error: ERROR: Prepare error: org.apache.hive.service.cli.HiveSQLException: Error while compiling statement: FAILED: ParseException line
1:452 extraneous input ',' expecting KW_THEN near ''line 1:626 extraneous input ',' expecting KW_THEN near ''
case when date_format(date_add(current_date, 1 - day(current_date)),'u')=6, then to_date(mydate) = date_add(date_add(current_date, 1 - day(current_date)+2))
when date_format(date_add(current_date, 1 - day(current_date)),'u')=7, then to_date(mydate) = date_add(date_add(current_date, 1 - day(current_date)+1))
else to_date(mydate) = date_add(date_add(current_date, 1 - day(current_date))) end
Please help!
#Vamsi Prabhala
I tried this however I receive a result of 1. I need a date returned, specifically 2/3/2020 for this month.
case when date_format(date_add(current_date, 1 - day(current_date)),'u')> 5 then
to_date(mydate)= to_date(date_add(date_add(current_date, 1 - day(current_date)),8-cast(date_format(date_add(current_date, 1 - day(current_date)),'u') as int)%8))
else to_date(mydate) = date_add(current_date, 1 - day(current_date)) end

One option is to get the first day in month and then add days if the first day in month is a weekend. By default weekday 1 = Monday, 2 = Tuesday ... 6 = Saturday, 7 = Sunday.
select dt
,case when date_format(first_day_in_month,'u') > 5
then date_add(first_day_in_month,8-cast(date_format(first_day_in_month,'u') as int))
else first_day_in_month end as first_week_day
from (select dt
,date_sub(dt,cast(date_format(dt,'d') as int)-1) as first_day_in_month
from tbl
) t
;
Note that the date_format function works in Hive versions 1.2.0 and above.

Related

Hive TimeStamp for Weekly and Quarterly data

The below hive command,
select * from my_new_table
where month(time_stamp)= '03'
and year(time_stamp) = '2016'
and age = '1'
and gender = '0'
and income = '4'
and ethnicity = '3'
and marital_status = '1';
generates the following results for all the data (31 days) for the month of March(03) 2016:
time_stamp age gender income ethnicity marital_status
2016-03-14#17:42:47.000 1 0 4 3 1
2016-03-14#16:10:51.000 1 0 4 3 1
2016-03-20#15:16:44.000 1 0 4 3 1
2016-03-14#17:13:51.000 1 0 4 3 1
2016-03-14#17:12:51.000 1 0 4 3 1
2016-03-14#18:24:51.000 1 0 4 3 1
2016-03-03#13:02:06.000 1 0 4 3 1
Similarly, I want to get the data for 2nd quarter of 2016 (or nth quarter, data should come for 3 months, starting March 1st till May 31st for this quarter ) and 12th week (or nth week, data should come for 7 days for this particular week) of 2016. What is the correct Hive command for this?
I'm getting error if I replace month with quarter or week in the Hive command.
select * from my_new_table
where quarter(time_stamp)='03'
and year(time_stamp) = '2016';
returns
FAILED: SemanticException [Error 10011]: Line 1:71 Invalid function 'quarter'
and
select * from my_new_table
where week(time_stamp)='12'
and year(time_stamp) = '2016';
returns
FAILED: SemanticException [Error 10011]: Line 1:71 Invalid function 'week'
Looks like there needs to be a calculation included in getting the nth quarter or week but not sure. Please help. Thanks.
The documentation says that month and week functions expect a "string date", not an actual date or timestamp type as input. You may need to use the date_format function to convert your timestamp to a string, then use the functions, like
month(date_format(timestamp, 'yyyy-MM-dd'))
This doesn't explain why your first example of these functions as part of the where clause seem to work, however.

Iterate over a table and update matching recordset - Access - Vba

Issue
I built a tracking system with unique workID and Ids that come from other tables. I have a column called multiplier that I will like to change if some conditions are met. I will like to change the multiplier column for every record where: the date is Sunday and is preceded by Saturday (meaning the date of the Saturday needs to be in the table) and has the same ID as the Saturday.
Basically this is a bonus system where if a runner worked on a Saturday and a Sunday, then on that Sunday he gets a multiplier of 2. I open recordset for every sunday and saturday present in the table and try to match them. But it skips some stuff because the saturday is not always followed by a sunday.
Code
sqlFindSat = "Select WorkID, Date, Task, ID, Multiplier from tblA where (weekday([date]) = 7) order by date, id, workId"
sqlFindSun = "select WorkID, Date, Task, ID, Multiplier from tblA where ( weekday([date]) = 1 ) order by date, id, workId"
Set fwSun = db.OpenRecordset(sqlFindSun)
Set fwSat = db.OpenRecordset(sqlFindSat)
Do While Not fwSat.EOF
waitforsat = False
debug.print " Curr Sat: " & fwSat!Date & " Curr Sun: " & fwSun!Date
If WeekdayName(Weekday(fwSat!Date)) = "saturday" Then
If ((DateAdd("d", 1, fwSat!Date) = fwSun!Date) And (fwSun!ID = fwSat!ID)) Then
fwSun.Edit
fwSun!multiplier = 2
fwSun.Update
End If
End If
If Not fwSun.EOF Then
fwSun.MoveNext
End If
fwSat.MoveNext
Loop
My code does this fine as long as the saturday is followed by a sunday. As soon as one saturday is not followed by a sunday, then the cursors are at different levels sometimes one is. I don't mind doing this in SQL Update or anything else as long as it works in access.
Note: the sample below isn't real sample. The comment section is to show what day of the week it is.
Sample table tblA
Workid | Date | ID | Multiplier | comments
12 10-11-2012 2 1 sunday
13 15-12-2012 4 1 Monday
14 10-10-2012 3 1 Saturday
25 11-10-2012 3 1 Sunday
17 8-10-2012 2 1 sunday
35 15-10-2012 4 1 Monday
45 8-10-2012 3 1 Saturday
50 9-10-2012 3 1 Sunday
Final output after running code on tblA:
Workid | Date | ID | Multiplier | comments
12 10-11-2012 2 1 Sunday
13 15-12-2012 4 1 Monday
14 10-10-2012 3 1 Saturday
25 11-10-2012 3 2 Sunday
17 8-10-2012 2 1 sunday
35 15-10-2012 4 1 Monday
45 8-10-2012 3 1 Saturday
50 9-10-2012 3 2 Sunday
As you can see from the table, the sundays that are preceded.
There's no need for VBA to do this; you might as well run a SQL query with a self-join and do the update directly.
This query would change the multiplier to 2 for all Sunday rows that have a record for the preceding Saturday with the same ID.
The syntax should be:
UPDATE tblA t1
INNER JOIN tblA t2 ON t1.ID = t2.ID AND t2.Date = DATEADD('d', -1, t1.date)
SET t1.Multiplier = 2
WHERE WEEKDAY(t1.date) = 1 -- assuming 1 is Sunday, might depend on regional setting
If you want to see what would happen before you do the update just change the update to a select * and remove the set statement.
Or make a backup of the table before you run it :)
Depending on how many records you are going to be accessing I think that this should work for you:
The first function is just to loop through all of the Sundays in the fwsat RecordSet. For each Sunday it will call the PrecedingSaturday function and will check to see if that ID has a Saturday that fell within one day of that Sunday.
Public Function CheckSunday()
sqlFindSat = "Select WorkID, Date, Task, ID, Multiplier from tblA where (weekday([date]) = 7) order by date, id, workId"
sqlFindSun = "select WorkID, Date, Task, ID, Multiplier from tblA where ( weekday([date]) = 1 ) order by date, id, workId"
Set fwSun = db.OpenRecordset(sqlFindSun)
Set fwsat = db.OpenRecordset(sqlFindSat)
'For all Sundays
Do While Not fwSun.EOF
'If this Sunday has a Preceding Saturday.
If PrecedingSaturday(fwsat, fwSun!id, fwSun!Date) Then
'Update multiplier to 2 for this Sunday
fwSun.Edit
fwSun!multiplier = 2
fwSun.Update
End If
fwSun.MoveNext
Loop
End Function
This function simply just accepts the RecordSet containing all of the Saturdays, and searches through them to see if any of them precedes the Sunday in question. If it does it returns true.
Public Function PrecedingSaturday(fwsat As Recordset, intID As Integer, dte As Date) As Boolean
Dim blnPrecedingSaturday As Boolean
blnPrecedingSaturday = False
'For all Saturdays while a preceding Saturday hasn't already been found
Do While Not fwsat.EOF And blnPrecedingSaturday = False
'If Saturday's ID and Sunday's id match
If fwsat!id = intID Then
'If the Saturday and Sunday happened within 1 day
If DateDiff("d", fwsat!Date, dte) = 1 Then
'This is a preceding Saturday
blnPrecedingSaturday = True
End If
End If
fwsat.MoveNext
Loop
PrecedingSaturday= blnPrecedingSaturday
End Function
This is rough code since I don't have the table structure to properly test it. Though I think it should work for what you are looking for.

How to get every Monday out of a Date

I need some help to understand a certain line in a code. The code takes the turnovers of every Monday in the year 2010 and at the last line in summarizes all the turnovers to one.
Here is the code:
SELECT
CASE
WHEN GROUPING (DATUM) = 1 THEN 'Gesamtumsatz'
ELSE CAST (DATUM AS VARCHAR (40))
END AS MONTAGSDATEN,
AVG (VERKAUFSWERT * VERKAUFSMENGE) as UMSATZ
FROM Data_Star_Awesome.dbo.VERKAUFSFAKTEN vk
INNER JOIN DIMDATUM dimD on vk.DATUMID=dimD.DATUMID
WHERE DATEDIFF(dd,0, DATUM)%7=0
AND JAHR = 2010
GROUP BY ROLLUP (DATUM)
The problematic line I don't understand is the following:
WHERE DATEDIFF(dd,0, DATUM)%7=0
What I know is that it takes the days out of the date variable but I don't get the %7=0 part. The DATEDIFF function should give back all the days. Are these days saved in the % the placeholder? And how does it get all the Mondays by using the 7=0?
It would be great if someone could help me out.
Thanks a lot :)
Modulo or % operator is the same as in a lot of programming languages. It returns the remainder after the division.
The DATEDIFF function takes two dates and returns the difference in a specified datepart, which in your query is the days represented by dd.
Also 0 as date converts to 1/1/1900 which happens to be a Monday. So your query is calculating the days between 1/1/1900 and the DATUM field in days and if its Mod is 0 then DATUM is Monday.
You could simply say:
datename(weekday,<datetime-value>)
Which will return 'Monday', 'Tuesday', 'Wednesday', etc. The problem with this approach is that the returned value is localized. If the SQL server's language is changed, your test for 'Monday' will fail.
This expression will always work:
( ##datefirst + ( datepart(weekday,today) - 1 ) ) % 7
It evaluates to 1-7, where Monday is always 1 and Sunday is always 7, regardless of culture/language settings or the current value of ##datefirst, as set by set datefirst.
We can then convert this into this discriminant function, yielding 1 or 0 to indicate whether or not the date is Monday:
case ( ##datefirst + ( datepart(weekday,today) - 1 ) ) % 7 when 1 then 1 else 0 end

Calculating Saturday and Sunday Business Date when Friday or Monday are a Holiday

I am working on a calendar generator in MS SQL 2008 and need to generate the correct business day for each day in the month. Everything is working with this exception: If Friday or Monday are a Holiday, then I get an erroneous value for the Business Dates for that weekend (Saturday and Sunday). I already have a column that returns a value of 1 if a Monday (MHDY) is a Holiday, and a separate column for Friday as well (FHldy) and what I am attempting to do is assign a value of 1 in the MHDY and FHldy columns for Saturday and Sunday, if the Friday before or Monday after are holidays. Here is the portion of Code that produces the values mentioned above:
SELECT
MC.[Date]
,MC.[Year]
,MC.[Quarter]
,MC.[Month]
,MC.[Week]
,MC.[Day]
,MC.[DayOfYear]
,MC.[Weekday] -- This has first day of week as Monday
,MC.[KindOfDay]
,MC.[Description]
,CASE WHEN Weekday BETWEEN 1 and 6 THEN Weekday +1
WHEN Weekday = 7 THEN 1 END AS [DayofWeek]
-- This will convert first day of week to Sunday
, CASE WHEN MC.KindOfDay = 'Holiday' THEN 1 ELSE 0 END AS Holiday
, CASE WHEN MC.KindOfDay <> 'BusDay' THEN 1 ELSE 0 END AS NonBDay
, CASE WHEN MC.KindOfDay = 'BusDay' THEN 1 ELSE 0 END AS BDay
, CASE WHEN MC.KindOfDay = 'Holiday' AND MC.Weekday = 1 THEN 1 ELSE 0 END AS MHDY
, CASE WHEN MC.Date = DateAdd(Month, 1, MC.Date - Day(MC.Date) + 1) -1 THEN 1 ELSE 0 END AS LDoM
, CASE WHEN MC.KindOfDay = 'Holiday' AND MC.[Weekday] = 5 THEN 1 ELSE 0 END AS FHldy
INTO #AllC2
FROM #MasterCal MC
There is much more code to the Calendar than this portion, but this is where I am attempting to add this information.
Is there a way to modify the CASE Statement to say "If Monday is a Holiday, return a value of 1 for Saturday and Sunday to MHDY." The same would apply for Fridays.
So close... this is the last hurdle. I appreciate any help you can offer.
The solution to the problem turned out to be simple.
I added lines to the CASE statement in the #MasterCal table to label Weekends before Monday holidays as Holidays in the KindOfDay field. the I added lines in the next section to tell it what date to assign those weekends that were listed as Holidays. Problem solved.

Adding relative week number column to MySQl results

I have a table with 3 columns: user, value, and date. The main query returns the values for a specific user based on a date range:
SELECT date, value FROM values
WHERE user = '$user' AND
date BETWEEN $start AND $end
What I would like is for the results to also have a column indicating the week number relative to the date range. So if the date range is 1/1/2010 - 1/20/2010, then any results from the first Sun - Sat of that range are week 1, the next Sun - Sat are week 2, etc. If the date range starts on a Saturday, then only results from that one day would be week 1. If the date range starts on Thursday but the first result is on the following Monday, it would be week 2, and there are no week 1 results.
Is this something fairly simple to add to the query? The only ideas I can come up with would be based on the week number for the year or the week number based on the results themselves (where in that second example above, the first result always gets week 1).
Example:
$start = "05/27/2010";
$end = "06/13/2010";
//Query
Result:
week date user value
1 05/28/2010 joe 123
3 06/07/2010 joe 123
3 06/08/2010 joe 123
4 06/13/2010 joe 123
This can easily be done with this simple and obvious expression :)
SELECT ...,
FLOOR(
(
DATEDIFF(date, $start) +
WEEKDAY($start + INTERVAL 1 DAY)
) / 7
) + 1 AS week_number;
Some explanation: this expression just calculates difference between the given date and the start date in days, then converts this number to weeks via FLOOR("difference in days" / 7) + 1. That's simple, but since this works only when $start is Sunday, we should add an offset for other week days: WEEKDAY($start + INTERVAL 1 DAY) which equals to 0 for Sun, 1 for Mon, ..., 6 for Sat.