Presto how to find start date given week - sql

I want to find start date from given ISO week (which can range from 1-53, Monday as starting day) and year using Presto SQL query.
i.e. year - 2020 and week - 2 should return 06/01/2020
Is there any inbuilt function for this ?
Table structure:
select year, week from table1; // returns year and week from table table 1

There's no direct way for constructing a date from a year + week (there is an issue for this: https://github.com/trinodb/trino/issues/2287), but you can achieve what you want with the date_parse function.
For example:
WITH data (year, week) AS (VALUES (2020, 2))
SELECT CAST(date_parse(CAST(year AS varchar) || ':' || CAST(week AS varchar), '%x:%v') AS date)
FROM data
produces:
_col0
------------
2020-01-06
(1 row)

Using DATE_ADD and MAKEDATE you can achieve the result...
select DATE_ADD(MAKEDATE(year, 1), INTERVAL (week-1) WEEK) as start_date from <table_name>;

Martin's answer is almost there. Instead of using year, you should use year_of_week. Though with this change you'll have to make sure to not have a bug with weeks that bleed into the following or previous year i.e. last days of the previous year or first days of the next year.
year_of_week returns the year of the ISO week.
Here's an example:
WITH data (year, week) AS (VALUES (2020, 2))
SELECT CAST(date_parse(CAST(year_of_week AS varchar) || ':' || CAST(week AS varchar), '%x:%v') AS date)
FROM data
References:
https://prestodb.io/docs/current/functions/datetime.html#year_of_week
https://en.wikipedia.org/wiki/ISO_week_date

I think for partial weeks (when first days in a new year is still counted as week 53) this does not work:
Query failed (#20210624_142222_02859_zf75v): Cannot parse "2021:53": Value 53 for weekOfWeekyear must be in the range [1,52]
tested by this formula:
The date was on Jan 2,2021 which is still treated as week53 but in 2021...
CAST(date_parse(CAST(year(date(service_order_creation_date)) AS varchar) || ':' || CAST(week(date(service_order_creation_date)) AS varchar), '%x:%v') AS date)

Related

Combine with month and year column kept in different columns on Oracle

I keep the month and year information in different columns as numbers.
I want to go back 12 months on sysdate using these columns.
The table I used below as an example ,
Since we are in the 5th month now, I want to get the data up to the 6th month of last year.
versiyon table :
So as a result of the query ,
the following result should return.
First of all, I want to query by combining the year and month columns and going back one year from the current month as a date.
Convert the values to strings and concatenate and then use ADD_MONTHS(SYSDATE, -12) to get last year's date (which will get the correct date regardless of whether it is a leap year or not):
SELECT *
FROM versiyon
WHERE TO_CHAR(year, 'fm0000') || TO_CHAR(month, 'fm00')
>= TO_CHAR(ADD_MONTHS(SYSDATE, -12), 'YYYYMM')
db<>fiddle here
select *
from versiyon
where lpad(year, 4, '0') || lpad(month, 2, '0') >= to_number(to_char(sysdate - 365, 'yyyymm' ))
Here is a demo
As MT0 say it will not work for leap years... so you can check if it is leap year or not with case when then end clause and using mod(year, 4) to check. In this demo I have created a situation as it is 2020, to be exact like it is 29th of February 2020. where you can see what I am suggesting in action:
DEMO2
You can convert your year and month into an integer form of YYYYMM and compare:
SELECT *
FROM versiyon_table
WHERE (versiyon_table.year * 100) + versiyon_table.month > (EXTRACT(YEAR FROM SYSDATE) * 100) + EXTRACT(MONTH FROM SYSDATE)

Create date from integers in separate fields in athena aws

I'm super new to athena, so bear with me. I have data stored as integers in three separate columns for year, month and day, as such:
year month day
2020 7 10
2020 7 11
2020 7 12
I'd like to turn these three fields into one date. How do I do that?
Thanks in advance!
One method is:
select date_parse(cast(year * 10000 + month * 100 + day as varchar(255)), '%Y%m%d')
This should also work:
select date(year || '-' || month || '-' || day)
You have to use the concat() function. You can see the documentation here.
Depending of the format that you want to use, this can change.
concat(year, '-' , month , '-', day)

Convert Year+WeekOfYear+DayOfWeek to a date

I have date values identified by a year, the week number within that year and the weekday and want to convert those into simple dates.
I couldn't find a function or another simple way to combine those, so I came up with a workaround using generate_series to get all dates in a range and JOIN the extracted values of those with my data:
SELECT data.*, days.d result
FROM ( VALUES (2017, 33, 3) ) data(d_year, d_week, d_weekday)
JOIN (
SELECT
-- the potential castdate
d::date d
-- year-week-dayofweek combination for JOINing
, EXTRACT('year' FROM d) d_year, EXTRACT('week' FROM d) d_week, EXTRACT('dow' FROM d) d_weekday
FROM generate_series('2015-01-01', '2019-12-31', INTERVAL '1day') AS days(d)
) days
USING(d_year, d_week, d_weekday)
Result is:
+--------+--------+-----------+------------+
| d_year | d_week | d_weekday | result |
+--------+--------+-----------+------------+
| 2017 | 33 | 3 | 16.08.2017 |
+--------+--------+-----------+------------+
While this works, this seems like overkill for such a simple task. Moreover, if one doesn't have a fixed range, this might not even work.
Is there an easier way to this?
demo:db<>fiddle
you can use the to_date() function, which takes an date string as argument, as well as a format pattern. So if the date string may be '2017-33-3', you could take this pattern to clarify each date part:
'IYYY-IW-ID'
'ID': The tricky part is: Does your week start with Sunday oder with Monday? This question influences the solution because it would shift the week numbers in an unexpected ways if you don't think about it. Thanks to your expected output, I saw you need 'ID' (ISO week day, week starts mondays) instead of 'D' (week day, week start sundays.)
'IW': Because we are taking the ISO week day, we need the ISO week of year as well (instead of 'WW': week of year)
'IYYY': Similar to (2)
More information about date patterns (especially the ISO thing): Postgres documentation
SELECT to_date(d_year || '-' || d_week || '-' || d_weekday, 'IYYY-IW-ID')
If you used the standard week pattern: 'YYYY-WW-D', your result would be 2017-08-13 (see fiddle)
Of course, this works also without the - characters, but it might be less readable:
SELECT to_date(d_year || d_week || d_weekday, 'IYYYIWID')

local week of the year in postgresql

I have to generate year wise, weekly reports for some data. Now When I aggregate date on week number, and week number is calculated from extract from creation date.
Now the problem is these both queries return week number 52.
SELECT EXTRACT(WEEK FROM TIMESTAMP '2006-01-01');
SELECT EXTRACT(WEEK FROM TIMESTAMP '2006-12-31');
First query return 52 (52nd week of 2005) and 2nd query return 52 (52nd week of year 2006). thats documented behavior.
But I want to Calculate local week number, and results for first query should be 1 and other query would return 53.
You can't do this with the exctract() function, it only supports ISO weeks.
But the to_char() function has an option for this:
SELECT to_char(DATE '2006-01-01', 'WW')::int` --> 1
SELECT to_char(DATE '2006-12-31', 'WW')::int` --> 53
For date 2006-01-01 end week is start in 2005 year, that same problem is 1999 year.
Clausule EXTRACT(WEEK getting year where week is started not ending.
You can use this code:
SELECT floor(EXTRACT(doy FROM TIMESTAMP '2006-01-01')/7 + 1);
SELECT floor(EXTRACT(doy FROM TIMESTAMP '2006-12-31')/7 + 1);

Finding the last day of the week

I have a table with a bunch of dates (option maturity dates to be precise). I need to query this database to find the last day of a specific week that is stored in the table.
All I will be given to query this table is the year, the month and the specific week. And based on this I need to find the date that is stored in the table that matches this.
I've created the following query to find this specific date March 28 2013
SELECT M_SETNAME, M_LABEL, M_MAT FROM OM_MAT_DBF
WHERE M_SETNAME = 'IMM_OSET '
AND MONTH(M_MAT) = 3
AND YEAR(M_MAT) = 2013
AND ((DATEPART(day,M_MAT)-1)/7 + 1) = 5
Do you guys have any idea of how I can change the last condition so that March 28th will be considered the 5th week of the month and not the 4th week as it is currently doing.
You can also use DATEPART to get the number of the week (in the year), but then, you could also get the 1st of each month, and take the week too so you can have: WEEK OF MY DATE - WEEK OF FIRST DAY FOR THIS MONTH + 1.
Here you have an example...
DECLARE #Dt datetime
SELECT #Dt='03-28-2013'
SELECT DATEPART( wk, #Dt) - DATEPART( wk, Convert(Date,Convert(varchar(4),YEAR(#Dt))
+ '-' + Convert(varchar(2), MONTH(#Dt))
+ '-' + Convert(varchar(2), 1))) + 1
EDIT: Also, looking at your code, you could add the CEILING. If the result == 2.7, it means it passed the 2nd week, however, it gets rounded to 2 when it should actually be 3.
If you add the CEILING and the CONVERT to decimal should work..
SELECT MONTH(#Dt),
YEAR(#Dt),
((CEILING(Convert(decimal,DATEPART(day,#Dt)-1)/7)) + 1)