Presto SQL date_format extract week of year - sql

Documentation : https://prestodb.io/docs/current/functions/datetime.html
I have epoch timestamps from which I want to extract week of the year like 2021-32, 2020-50, 2021-02 and so on.
SELECT concat(date_format(from_unixtime((CAST(my_timestamp AS BIGINT) + 19800000)/1000), '%Y'),
'-' ,
date_format(from_unixtime((CAST(my_timestamp AS BIGINT) + 19800000)/1000), '%v'))
AS week
However I am getting up some wrong values like :
week = 2021-53 for Epoch-Time corresponding to Jan 1, 2021 or Jan 2, 2021. I understand that there is a sync issue happening here but that is definitely not something I want - How do I offset so that first day of week 1 starts from the beginning of the year.

In that case you should just get the count of days and calculate the week.
Something like this:
SELECT concat(date_format(from_unixtime((CAST(my_timestamp AS BIGINT) + 19800000)/1000), '%Y'),
'-' ,
ceiling(date_format(from_unixtime((CAST(my_timestamp AS BIGINT) + 19800000)/1000), '%j')/7))
AS week

I was able to solve it using week_of_year and year_of_week methods.
Docs : https://prestodb.io/docs/current/functions/datetime.html#week
Query :
SELECT concat(CAST(year_of_week(from_unixtime((CAST(my_timestamp AS BIGINT) + 19800000)/1000)) AS varchar(15)),
'-',
CAST(week_of_year(from_unixtime((CAST(my_timestamp AS BIGINT) + 19800000)/1000)) AS varchar(15))) as week
Had to introduce some extra casts to varchar since concat doesn't support multiple datatypes.
Edit :
Another issue with above solution is that week_of_year returns single-digit weeks like 1, 2 instead of 01, 02 - thus causing an issue while sorting with these week numbers.
I ended up using a combination of year_of_week to get the correct year, and the general date_format(date, '%v') for week-numbers.
Updated Query :
SELECT concat(CAST(year_of_week(from_unixtime((CAST(my_timestamp AS BIGINT) + 19800000)/1000)) AS varchar(15)),
'-',
date_format(from_unixtime((CAST(my_timestamp AS BIGINT) + 19800000)/1000), '%v'))

There is no sync issue here - it expected behaviour for date_format and it's MySQL counterpart.
Note, that you can use full format string on the date:
select date_format(timestamp '2021-01-01', '%Y-%v')
_col0
2021-53
You can try calculating week number by dividing day_of_year by 7:
select ceiling(day_of_year(timestamp '2021-01-01') / 7.0)
Related:
presto github issue
joda weekOfWeekyear docs

Related

Convert whole number to Month-Year

I am working in SQL Server, I have a column of numbers that represent the year and the month, such as:
YearandMonth
------------
202108
202109
202110
How do I convert this to an output like this?
YearandMonth
------------
Aug-2021
Sept-2021
Oct-2021
Thank you in advance
Steps:
Get the year and the month from the number.
Create a date from the year and the month.
Get the abbreviated month name from that date.
Concatenate month name and year.
The query:
select
format(datefromparts(yearanddate / 100, yearanddate % 100, 1), 'MMM', 'en-US') +
'-' +
cast(yearanddate / 100 as varchar(4))
from mytable;
select DATE_FORMAT(CONCAT(`yearandmonth`,'01'), '%b-%Y') as 'YearandMonth' from test_table;
by adding the 1st day of each month it provides the standard format so we can just use DATE_FORMAT() to get the result we need.
For SQL Server 2008 this should work fine. Untested, of course:
with myTable as (
select * from (values(202108),(202109),(202110))v(YearAndMonth)
)
select Left(DateName(month,Convert(date,Cast(YearAndMonth *100+1 as varchar(8)))),3) + '-' + Left(Cast(YearAndMonth as varchar(6)),4)
from myTable

Hardcode a specific day in data time while pulling the data - SQL

Actually I have different date in SQL table when I pull those via SQL query, day of datetime field should have fixed day.
Example: (DD-MM-YYYY) day should be "7" > (7-MM-YYYY)
10-08-2007 > 07-08-2007
27-12-2013 > 07-12-2013
01-03-2017 > 07-03-2017
Can someone help me on this. Thanks in Advance.
Find the difference between 7 and the day of the original date and add that to the original date:
SELECT DATEADD(DAY, 7 - DAY(OriginalDate), OriginalDate)
Use DATEPART to take out the month and year parts. Cast those into varchar and concatenate with 07.
Query
select '07-' +
cast(DATEPART(mm, [date_column]) as varchar(2)) + '-' +
cast(DATEPART(yyyy, [date_column]) as varchar(4))
from your_table_name;
Assuming You might have to change the day number example
DECLARE #dayNum char(2)
SELECT #dayNum = '07'
select #dayNum + Right(convert(char(10),getdate(),105),8)
If that is not the case You could do this
select '07'+ Right(convert(char(10),'10-08-2007',105),8)
I'd go this way:
SELECT CONVERT(DATE,CONVERT(VARCHAR(6),GETDATE(),112)+'25',112);
CONVERT with format 112 will return the date as unseparated ISO (today we would get 20170407). Convert this to VARCHAR(6) will implicitly cut away the day's part (201704).
Now we add a day and use again CONVERT with 112, but now with DATE as target type.
One thing to keep in mind: The day you add must be two-digit. You can achieve this with
DECLARE #int INT=7;
SELECT REPLACE(STR(#int,2),' ','0');
Use DATEFROMPARTS: Updated ONLY works from 2012 - OP has tagged SQL-Server 2008
select DATEFROMPARTS ( year('10-08-2007'), month('10-08-2007'), 7 )
Assuming that your field is of datetime datatype and your fixed day is of integer type.
select datetimecolumn+(yourparamfixedday-datepart(dd,datetimecolumn))

Selecting YYYYMM of the previous month in HIVE

I am using Hive, so the SQL syntax might be slightly different. How do I get the data from the previous month? For example, if today is 2015-04-30, I need the data from March in this format 201503? Thanks!
select
employee_id, hours,
previous_month_date--YYYYMM,
from
employees
where
previous_month_date = cast(FROM_UNIXTIME(UNIX_TIMESTAMP(),'yyyy-MM-dd') as int)
From experience, it's safer to use DATE_ADD(Today, -1-Day(Today)) to compute last-day-of-previous-month without having to worry about edge cases. From there you can do what you want e.g.
select
from_unixtime(unix_timestamp(), 'yyyy-MM-dd') as TODAY,
date_add(from_unixtime(unix_timestamp(), 'yyyy-MM-dd'), -1-cast(from_unixtime(unix_timestamp(), 'd') as int)) as LAST_DAY_PREV_MONTH,
substr(date_add(from_unixtime(unix_timestamp(), 'yyyy-MM-dd'), -1-cast(from_unixtime(unix_timestamp(), 'd') as int)), 1,7) as PREV_MONTH,
cast(substr(regexp_replace(date_add(from_unixtime(unix_timestamp(), 'yyyy-MM-dd'), -1-cast(from_unixtime(unix_timestamp(), 'd') as int)), '-',''), 1,6) as int) as PREV_MONTH_NUM
from WHATEVER limit 1
-- today last_day_prev_month prev_month prev_month_num
-- 2015-08-13 2015-07-30 2015-07 201507
See Hive documentation about date functions, string functions etc.
below works across year boundaries w/o complex calcs:
date_format(add_months(current_date, -1), 'yyyyMM') --previous month's yyyyMM
in general,
date_format(add_months(current_date, -n), 'yyyyMM') --previous n-th month's yyyyMM
use proper sign for needed direction (back/ahead)
You could do (year('2015-04-30')*100+month('2015-04-30'))-1 for the above mentioned date, it will return 201503 or something like (year(from_unixtime(unix_timestamp()))*100+month(from_unixtime(unix_timestamp())))-1 for today's previous month. Assuming your date column is in 'yyyy-mm-dd' format you can use the first example and substitute the date string with your table column name; for any other format the second example will do, add the column name in the unix_timestamp() operator.
Angelo's reply is a good start but it returns 201500 if the original date was 2015-01-XX. Building on his answer, I suggest using the following:
IF(month(${DATE}) = 1,
(year(${DATE})-1)*100 + 12,
year(${DATE})*100 + month(${DATE})-1
) as month_key
provided you get rid of those hyphens in your input string , previous date's month id in YYYYMM format you can get by:-
select if( ((${hiveconf:MonthId}-1)%100)=0 ,${hiveconf:MonthId}-89,${hiveconf:MonthId}-1 ) as PreviousMonthId;

Cast Function to display only the month and day from a datetime

SELECT
DateAdded,
Cast(DateAdded AS Date) AS DateAddedV1,
Cast(DateAdded AS Time) AS DateTime,
SELECT CAST(DateAdded AS Date(mm:dd) AS OrderDate
FROM Products
I am a beginner with SQL and I am trying to return the DateAdded column as OrderDate with only the month and the day but I cannot seem to get the syntax right. I appreciate anyone's assistance.
Use DatePart Function to extract day and month from Datetime type,
Select Datepart(Month,DateAdded) AS [Month], -- Month(Dateadded)
Datepart(Day,DateAdded) as [Day], -- Day(Dateadded)
..
From Products
Update: Only by using cast function you cannot extract Month and Day. If you want to keep month and day in same column
SELECT CONVERT(VARCHAR(2), Month(DateAdded)) + ':'
+ CONVERT(VARCHAR(2), Day(DateAdded))
.....
To get leading zero's use right function and to extract Time from DateAdded use Convert function with 108 value
SELECT right('0'+CONVERT(VARCHAR(2), Month(DateAdded)),2) + ':'
+ right('0'+CONVERT(VARCHAR(2), Day(DateAdded)) ,2) as [Mon:Day],
convert(varchar(10),DateAdded,108) as [Time]
.........
I think I'm working on this assignment this semester. This is what I ended up with since it HAD to be done using the CAST function:
SELECT DateAdded,
CAST(DateAdded AS date) AS DateOnly,
CAST(DateAdded AS time) AS TimeOnly,
CAST(DateAdded AS varchar(6)) MonthDay
FROM Products;
This works because varchar always has the Month the Day exactly in the first 6 characters. All the Months are 3 Characters (Jan, Feb, Mar, Apr) and then there is either a space then a 2-digit day, or 2 spaces and a 1-digit day. Either way it always adds up to 6 characters.
Here you are asking about the visible format of date/time information.
In MS SQL Server from SQ 2012 and later you can use a FORMAT()
function. If you use a version that supports this function I recommend you use it. Keep in mind that the second parameter is CASE SENSITIVE
In all versions you may use the CONVERT() function, which has
this syntax:
CONVERT ( data_type [ ( length ) ] , expression [ , style ] )
Note in paticular that style parameter (an integer) this is important if using CONVERT. A very useful reference for using either approach for display of date/time information is HERE and below is a tiny example:
SQL Fiddle demo
Query 1:
SELECT
FORMAT(SYSDATETIME(), 'MMM dd yyyy')
, CONVERT(VARCHAR(11), SYSDATETIME(), 100) -- note length set to (11)
Results:
|-------------|-------------|
| Oct 11 2015 | Oct 11 2015 |
Instead of converting, as in NoDisPlayName's answer, you could use the RTRIM functionality.
SELECT RIGHT('0' + RTRIM(MONTH(DateAdded)), 2)

Date arithmetic in SQL on DB2/ODBC

I'm building a query against a DB2 database, connecting through the IBM Client Access ODBC driver. I want to pull fields that are less than 6 days old, based on the field 'a.ofbkddt'... the problem is that this field is not a date field, but rather a DECIMAL field, formatted as YYYYMMDD.
I was able to break down the decimal field by wrapping it in a call to char(), then using substr() to pull the year, month and day fields. I then formatted this as a date, and called the days() function, which gives a number that I can perform arithmetic on.
Here's an example of the query:
select
days( current date) -
days( substr(char(a.ofbkddt),1,4) concat '-' -- YYYY-
concat substr(char(a.ofbkddt),5,2) concat '-' -- MM-
concat substr(char(a.ofbkddt),7,2) ) as difference, -- DD
a.ofbkddt as mydate
from QS36F.ASDF a
This yields the following:
difference mydate
2402 20050402
2025 20060306
...
4 20110917
3 20110918
2 20110919
1 20110920
This is what I expect to see... however when I use the same logic in the where clause of my query:
select
days( current date) -
days( substr(char(a.ofbkddt),1,4) concat '-' -- YYYY-
concat substr(char(a.ofbkddt),5,2) concat '-' -- MM-
concat substr(char(a.ofbkddt),7,2) ) as difference, -- DD
a.ofbkddt as mydate
from QS36F.ASDF a
where
(
days( current date) -
days( substr(char(a.ofbkddt),1,4) concat '-' -- YYYY-
concat substr(char(a.ofbkddt),5,2) concat '-' -- MM
concat substr(char(a.ofbkddt),7,2) ) -- DD
) < 6
I don't get any results back from my query, even though it's clear that I am getting date differences of as little as 1 day (obviously less than the 6 days that I'm requesting in the where clause).
My first thought was that the return type of days() might not be an integer, causing the comparison to fail... according to the documentation for days() found at http://publib.boulder.ibm.com/iseries/v5r2/ic2924/index.htm?info/db2/rbafzmst02.htm, it returns a bigint. I cast the difference to integer, just to be safe, but this had no effect.
You're going about this backwards. Rather than using a function on every single value in the table (so you can compare it to the date), you should pre-compute the difference in the date. It's costing you resources to run the function on every row - you'd save a lot if you could just do it against CURRENT_DATE (it'd maybe save you even more if you could do it in your application code, but I realize this might not be possible). Your dates are in a sortable format, after all.
The query looks like so:
SELECT ofbkddt as myDate
FROM QS36F.ASDF
WHERE myDate > ((int(substr(char(current_date - 6 days, ISO), 1, 4)) * 10000) +
(int(substr(char(current_date - 6 days, ISO), 6, 2)) * 100) +
(int(substr(char(current_date - 6 days, ISO), 9, 2))))
Which, when run against your sample datatable, yields the following:
myDate
=============
20110917
20110918
20110919
20110920
You might also want to look into creating a calendar table, and add these dates as one of the columns.
What if you try a common table expression?
WITH A AS
(
select
days( current date) -
days( substr(char(a.ofbkddt),1,4) concat '-' -- YYYY-
concat substr(char(a.ofbkddt),5,2) concat '-' -- MM-
concat substr(char(a.ofbkddt),7,2) ) as difference, -- DD
a.ofbkddt as mydate
from QS36F.ASDF a
)
SELECT
*
FROM
a
WHERE
difference < 6
Does your data have some nulls in a.ofbkddt? Maybe this is causing some funny behaviour in how db2 is evaluating the less than operation.