Why SparkSQL is not giving the right day of the week? - sql

I have this query in SparkSQL.
WITH a AS (
SELECT OrderDts,
CASE EXTRACT(DAYOFWEEK FROM OrderDts)
WHEN 1 THEN 'Mon'
WHEN 2 THEN 'Tues'
WHEN 3 THEN 'Wed'
WHEN 4 THEN 'Thu'
WHEN 5 THEN 'Fri'
WHEN 6 THEN 'Sat'
WHEN 7 THEN 'Sun'
END as dayofweek
FROM Orders
)
SELECT * FROM a
ORDER BY OrderDts DESC
However, I get the wrong day name. For example, it shows me the following.
2021-05-10 05:58 Tues
While 10 May is actually Monday. Any idea why this problem occurs and how to solve it?

The docs says:
"DAYOFWEEK",("DOW") - the day of the week for datetime as Sunday(1) to
Saturday(7) "DAYOFWEEK_ISO",("DOW_ISO") - ISO 8601 based day of the
week for datetime as Monday(1) to Sunday(7)
So you can use DAYOFWEEK_ISO instead of DAYOFWEEK, or change the list of when statements.

by the way in Hive yo could simply use this to get name of day :
select date_format(current_date,'EEEE');

Related

Rolling back on query one day before SQL

I am trying to make a query in which for every weekday, it picks always the last business day, except for Mondays. On Mondays, it should always pick the last Friday.
To achieve this, it could be either done by selecting or creating an additional column that allows to identify these cases.
Examples:
If first_date = Tuesday then pick Monday
If first_date = Thursday then pick Wednesday
If first_date = Monday then pick Friday
Here my query:
SELECT name,
first_date,
last_day,
product,
TO_DATE(first_date) - TO_DATE(last_day) AS d,
CASE WHEN TO_CHAR(first_date, 'D') = '7' THEN -2
WHEN TO_CHAR(first_date, 'D') = '6' THEN -1
ELSE 0
END
FROM t1.mydata
WHERE d > 50
Any ideas on how to do this best?
You can use conditional with TO_CHAR conversion along with Dy (or Day) argument rather than using those integer representations, those might fail for some regions, for weekdays such that
SELECT CASE WHEN TO_CHAR(your_datecol,'Dy','NLS_DATE_LANGUAGE=English') ='Mon' THEN
'Fri'
WHEN TO_CHAR(your_datecol,'Dy','NLS_DATE_LANGUAGE=English') = 'Sun' THEN
Null
ELSE
TO_CHAR(your_datecol-1,'Dy','NLS_DATE_LANGUAGE=English')
END AS last_business_day
FROM your_table
ignoring the local offical vacancies.
You can use TRUNC(first_date) - TRUNC(fisrt_date, 'IW') to compare the date (truncated to midnight) to the start of the ISO week (which is always midnight on Monday). This will work regardless of the NLS_DATE_LANGUAGE or NLS_TERRITORY settings.
SELECT name,
first_date,
last_day,
product,
last_day - first_date AS d,
first_date
- CASE TRUNC(first_date) - TRUNC(fisrt_date, 'IW')
WHEN 0 THEN -3 -- Monday
WHEN 6 THEN -2 -- Sunday
ELSE -1 -- Other days
END AS prev_business_day
FROM t1.mydata
WHERE last_day - first_date > 50
Note: If you use TO_CHAR(first_date, 'D') then if the day is Monday then it will return: 1 in most of Europe; 2 in America; 3 in some Middle-Eastern countries; and 4 in Bangladesh as they all consider the first day of the week to be a different day db<>fiddle. This is based on the NLS_TERRITORY setting and is not something that can be overridden in the query.
Note: If you use TO_CHAR(first_date, 'Dy') then it will use the NLS_DATE_LANGUAGE session parameter to set the date language so your query would only work in one language. You would need to specify a third argument (i.e. TO_CHAR(first_date, 'Dy', 'NLS_DATE_LANGUAGE=English')) for it to work consistently in an International setting.

Finding the WEEK number for 1st January - Big Query

I am calculating the first week of every month for past 12 months from current date. The query logic that I am using is as follows:
SELECT
FORMAT_DATE('%Y%m%d', DATE_TRUNC(DATE_SUB(CURRENT_DATE(),interval 10 month), MONTH)) AS YYMMDD,
FORMAT_DATE('%Y%m', DATE_TRUNC(DATE_SUB(CURRENT_DATE(), interval 10 month), MONTH)) AS YYMM,
FORMAT_DATE('%Y%W', DATE_TRUNC(DATE_SUB(CURRENT_DATE(), interval 10 month), MONTH)) AS YYWW
OUTPUT:
Row
YYMMDD
YYMM
YYWW
1
20210101
202101
202100
The YYWW format returns the week as 00 and is causing my logic to fail. Is there anyway to handle this? My logic is going to be running 12 months calculation to find first week of every month.
At a very basic level, you can accomplish it with something like this:
with calendar as (
select date, extract(day from date) as day_of_month
from unnest(generate_date_array('2021-01-01',current_date(), interval 1 day)) date
)
select
date,
extract(month from date) as month_of_year,
case
when day_of_month < 8 then 1
when day_of_month < 15 then 2
when day_of_month < 22 then 3
when day_of_month < 29 then 4
else 5
end as week_of_month
from calendar
order by date
This approach is very simplistic, but you gave no criteria for your week-of-month definition in the query, so this is a reasonable answer. There is potential for a ton of variation in how you define week-of-month. The logic for week-of-year is built in to BQ, and provides options to handle items such as the starting day of the week, carryover at the end/beginning of consecutive years, etc. There is no corresponding week-of-month logic out of the box, so any "easy" built-in function like FORMAT_DATE() is unlikely to solve the problem.

ORACLE Find Date ('DD-MON-YYYY') of a given weekday in the past 7 days

i am trying to create a view that compares a SCHEDULE table that has values such as ('Daily', 'Wednesday', 'Tuesday', etc..) and another table (REPORT CREATED) that is updated every day with dates (11-AUG-2017). Basically, if the Schedule table shows Daily, then the Report Created table record value should be whatever sysdate (current date) is equal to. That said, I'm not sure how to find out what the most recent 'Wednesday' or 'Tuesday' is equal to. I did find a function for SQL server (How to get Saturday's Date (Or any other weekday's Date)- SQL Server) ; however, I do not understand how it works and can't find an equivalent in Oracle. Any guidance would be greatly appreciated!
Edit: I have created two sample tables:
Schedules Table:
Report_Name | Frequency
ORDERS_BY_DEPT | Daily
LOW_STOCK | Wednesday
INVENTORY_DISC | Thursday
and the Reports Table:
Report_Name | Create_Dt
INVENTORY_DISC | 3-Aug-2017
LOW_STOCK | 9-Aug-2017
ORDERS_BY_DEPT | 10-Aug-2017
So essentially, the Inventory_Disc report is off, since it should have ran every Thursday but hasn't been updated since last Thursday and the Orders_By_Dept report is off since it is a daily report and didn't run today.
Use the NEXT_DAY( date_value, day_string ) function. Take the current day (SYSDATE) and subtract 7 days from it and then find the next day which matches your required day-of-the-week.
So, to get the most recent Wednesday:
SELECT NEXT_DAY( TRUNC( SYSDATE ) - 7, 'WEDNESDAY' )
FROM DUAL
You can find the day of the week with:
to_char(sysdate, 'D')
So for example, the last Thursday is:
select case
when to_char(sysdate, 'D') < 4 then sysdate - to_char(sysdate, 'D') - 7 + 4
else sysdate - to_char(sysdate, 'D') + 4
end
from dual

Why I lost the days from 2-6? It shows always days in a 7 days turn

TRUNC (ADD_MONTHS(DATE, - CASE WHEN COUNTRYCODE='TH'
AND DATE >= (CURRENT_DATE+1)
THEN 6516 ELSE 0 END)
, 'day' ) as RDATE,
When you use TRUNC(DATE,'DAY') then it expected to display the date based on first day of week. Please refer link here where you can see below. That is the reason, you loose 2 to 6 days.
TRUNC(TO_DATE('22-AUG-03'), 'DAY')
Result: '17-AUG-03'

Hive date function to achieve day of week

I'm looking for a workaround or hive date functions that gives day of the week ,
Sunday - 1
Monday - 2
Tuesday - 3
Wednesday - 4
Thursday - 5
Friday - 6
Saturday - 7
Requirement in detail : I'm looking for a function that takes date string (YYYYMMDD) as input and outputs the day of the week as per the above table.
Consider using from_unixtime(your date,'u') - this will return day number of week starting from Monday=1.
If your date is not in unixtime format, you can use the following instead:
from_unixtime(unix_timestamp('20140112','yyyyMMdd'),'u')
see: http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html for simple date format documentation.
You can now use date_format (Hive 1.2):
hive> select date_format('2016-12-01' ,'u');
OK
4
select pmod(datediff(your_date,'1900-01-07'),7) + 1 as WeekDay from your_table
arbitrary start date picked (1900-01-07)
calculates the mod 7 day of week (plus 1 to start at 1 instead of zero)
Expanding on iggy's answer, here is the query to get the days of the week. Adjust the query to set the first day of the week as necessary.
SELECT current_date AS `Date`,
CASE date_format(current_date,'u')
WHEN 1 THEN 'Mon'
WHEN 2 THEN 'Tues'
WHEN 3 THEN 'Wed'
WHEN 4 THEN 'Thu'
WHEN 5 THEN 'Fri'
WHEN 6 THEN 'Sat'
WHEN 7 THEN 'Sun'
END AS day_of_week
From Hive 2.2 there is another possibility:
hive> select extract(dayofweek FROM your_date) FROM your_table;
As I said you need to write a UDF which will accept a string as parameter and return a string.
Inside the UDF you need to do these steps:
1.) Parse the input string using SimpleDateFormat(YYYYMMDD)
2.) Use the Below code to get the day of week:
Calendar c = Calendar.getInstance();
c.setTime(yourDate);
int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);
3.) Use this dayOfWeek value in a case statement to get your weekday String and return that string.
Hope this helps...!!!