Convert Name of day to number -e.g- Monday to 1 - amazon-redshift

I don't have timestamp table. I just need to convert using name string,
SELECT day_of_week;
Output should look like
day_of_week sum
Friday 5
Monday 1
Saturday 6
Sunday 7
Thursday 4
Tuesday 2
Wednesday 3

If it were timestamp then you can use the isodow. See doc
isodow
The day of the week as Monday(1) to Sunday(7)
SELECT day_of_week, EXTRACT(ISODOW FROM TIMESTAMP '2001-02-18 20:38:40') as sum FROM your_table;
But you don't have that column. So you can use CASE...WHEN like below-
SELECT day_of_week,
CASE WHEN day_of_week='Monday' THEN 1
WHEN day_of_week='Tuesday' THEN 2
WHEN day_of_week='Wednesday' THEN 3
WHEN day_of_week='Thursday' THEN 4
WHEN day_of_week='Friday' THEN 5
WHEN day_of_week='Saturday' THEN 6
ELSE 7
END as sum
FROM your_table;
See doc: https://www.postgresql.org/docs/8.4/functions-conditional.html

Related

How to Average by day of week in Google Sheets?

Given a table of dates and values.
How to average by day of week?
I found AVERAGEIF to average and TEXT(E4, "dddd") to convert to day of week.
But how to combine those two functions?
Date
Value
1/1/2001
1
1/2/2001
2
1/3/2001
3
1/4/2001
3
1/5/2001
6
1/6/2001
3
Day of Week
Average
Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
Go with QUERY() function. Try-
=QUERY({INDEX(TEXT(A1:A15,"dddd")),B1:B15},
"select Col1, avg(Col2) group by Col1 label Col1 'Day', avg(Col2) 'Average'")
To make it dynamic, use-
=QUERY({INDEX(TEXT(TOCOL(A1:A,1),"dddd")),TOCOL(B1:B,1)},
"select Col1, avg(Col2) group by Col1 label Col1 'Day', avg(Col2) 'Average'")

how to filter my database with only "Monday" queries?

I am trying to extract only monday from timestamp (in time,date,month format) in my database (would do count on it after wards). I tried to convert my dates to string characters. I was able to get all days in text format.
select to_char (payment_date, 'dy') as days from payment;
however, when i try to add where in it, to filter days, it gives an error.
select to_char (payment_date, 'dy') as days
from payment
where days.payment_date = 'mon';
You might want something like this (all of the code below is available on the fiddle here):
Generate a table with all of the dates in the first half of 2022.
CREATE TABLE dat AS
SELECT the_day FROM GENERATE_SERIES
('2022-01-01'::TIMESTAMPTZ, '2022-06-30'::TIMESTAMPTZ, '1 DAY') AS t(the_day);
and then run:
SELECT
the_day::DATE,
EXTRACT(ISODOW FROM the_day),
to_char(the_day, 'Day')
FROM
dat
WHERE
EXTRACT(ISODOW FROM the_day) = 1;
Result:
the_day extract to_char
2022-01-03 1 Monday
2022-01-10 1 Monday
2022-01-17 1 Monday
2022-01-24 1 Monday
2022-01-31 1 Monday
2022-02-07 1 Monday
2022-02-14 1 Monday
2022-02-21 1 Monday
2022-02-28 1 Monday
2022-03-07 1 Monday
...
... snipped for brevity
...
or similarly:
SELECT
the_day::DATE,
EXTRACT(ISODOW FROM the_day),
to_char(the_day, 'DAY')
FROM
dat
WHERE
to_char(the_day, 'DAY') = 'WEDNESDAY';
Result:
the_day extract to_char
2022-01-05 3 WEDNESDAY
2022-01-12 3 WEDNESDAY
2022-01-19 3 WEDNESDAY
2022-01-26 3 WEDNESDAY
2022-02-02 3 WEDNESDAY
2022-02-09 3 WEDNESDAY
...
... snipped for brevity
...

Get week number, with weeks starting on Sunday, like Excel WEEKNUM

In PostgreSQL (I'm on version 9.6.6), what's the simplest way to get the week number, starting on Sunday?
DATE_PART('week',x) returns:
The number of the ISO 8601 week-numbering week of the year. By definition, ISO weeks start on Mondays and the first week of a year contains January 4 of that year. In other words, the first Thursday of a year is in week 1 of that year. (doc)
Say my query is like:
WITH dates as (SELECT generate_series(timestamp '2014-01-01',
timestamp '2014-01-31',
interval '1 day'
)::date AS date
)
SELECT
date,
TO_CHAR(date,'Day') AS dayname,
DATE_PART('week',date) AS weekofyear
FROM dates
Returns:
date dayname weekofyear
--------------------------------
2014-01-01 Wednesday 1
2014-01-02 Thursday 1
2014-01-03 Friday 1
2014-01-04 Saturday 1
2014-01-05 Sunday 1 <- I want this to be 2
2014-01-06 Monday 2
2014-01-07 Tuesday 2
2014-01-08 Wednesday 2
So far I have tried:
SELECT
date,
TO_CHAR(date,'Day') AS dayname,
DATE_PART('week',date) AS week_iso,
DATE_PART('week',date + interval '1 day') AS week_alt
FROM dates
which won't quite work if the year begins on a Sunday.
Also, I want week 1 to contain January 1 of that year. So if January 1 is a Saturday, I want week 1 to be one day long (instead of being week 53 in the ISO style). This behavior is consistent with the Excel WEEKNUM function.
To get the week number of the year, with weeks starting on Sunday, we need to know how many Sundays between the first day of the year and the target date.
I adapted the solution here by #Erwin Brandstetter. This solution counts Sundays inclusive of the first day of the year and exclusive of the target date.
Then, because I want the first (partial) week to be week one (not zero), I need to add 1 unless the first day of the year is a Sunday (in which case it's already week one).
WITH dates as (SELECT generate_series(timestamp '2014-01-01',
timestamp '2014-01-31',
interval '1 day'
)::date AS date
)
SELECT
date,
TO_CHAR(date,'Day') AS dayname,
DATE_PART('week',date) AS week_iso,
((date - DATE_TRUNC('year',date)::date) + DATE_PART('isodow', DATE_TRUNC('year',date)) )::int / 7
+ CASE WHEN DATE_PART('isodow', DATE_TRUNC('year',date)) = 7 THEN 0 ELSE 1 END
AS week_sundays
FROM dates
Returns
date dayname weekofyear week_sundays
--------------------------------
2014-01-01 Wednesday 1 1
2014-01-02 Thursday 1 1
2014-01-03 Friday 1 1
2014-01-04 Saturday 1 1
2014-01-05 Sunday 1 2
2014-01-06 Monday 2 2
2014-01-07 Tuesday 2 2
To show how this works for years starting on Sunday:
2017-01-01 Sunday 52 1
2017-01-02 Monday 1 1
2017-01-03 Tuesday 1 1
2017-01-04 Wednesday 1 1
2017-01-05 Thursday 1 1
2017-01-06 Friday 1 1
2017-01-07 Saturday 1 1
2017-01-08 Sunday 1 2
The task is not as daunting as it first appears. It mainly requires finding the first Sun on or after the 1-Jan. That date becomes the last day of the first week. From there calculation of subsequent weeks is merely. a matter of addition. The other significant point is with week definition there will always be 53 week per year and the last day of the last week is 31-Dec. The following generates an annual calendar for this week definition.
create or replace function non_standard_cal(year_in integer)
returns table (week_number integer, first_day_of_week date, last_day_of_week date)
language sql immutable leakproof strict rows 53
as $$
with recursive cal as
(select 1 wk, d1 start_of_week, ds end_of_week, de stop_date
from (select d1+substring( '0654321'
, extract(dow from d1)::integer+1
, 1)::integer ds
, d1, de
from ( select make_date (year_in, 1,1) d1
, make_date (year_in+1, 1,1) -1 de
) a
) b
union all
select wk+1, end_of_week+1, case when end_of_week+7 > stop_date
then stop_date
else end_of_week+7
end
, stop_date
from cal
where wk < 53
)
select wk, start_of_week, end_of_week from cal;
$$ ;
As a general rule I avoid magic numbers, but sometimes they're useful; as in this case. In magic number (actually a string) '0654321' each digit represents the number of days needed to reach the first Mon on or after 1-Jan when indexed by the standard day numbering system (0-6 as Sun-Sat). The result is the Mon being the last day of the first week. That generatess the 1st row of the recursive CTE. The remaining rows just add the appropriate number days for each week until the 53 weeks have been generated. The following shows the years needed to ensure each day of week gets it's turn to 1-Jan (yea some days duplicate). Run individual years to validate its calendar.
do $$
declare
cal record;
yr_cal cursor (yr integer) for
select * from non_standard_cal(2000+yr) limit 1;
begin
for yr in 18 .. 26
loop
open yr_cal(yr);
fetch yr_cal into cal;
raise notice 'For Year: %, week: %, first_day: %, Last_day: %, First day is: %'
, 2000+yr
,cal.week_number
,cal.first_day_of_week
,cal.last_day_of_week
,to_char(cal.first_day_of_week, 'Day');
close yr_cal;
end loop;
end; $$;
Following may work - tested with two cases in mind:
WITH dates as (SELECT generate_series(timestamp '2014-01-01',
timestamp '2014-01-10',
interval '1 day'
)::date AS date
union
SELECT generate_series(timestamp '2017-01-01',
timestamp '2017-01-10',
interval '1 day'
)::date AS date
)
, alt as (
SELECT
date,
TO_CHAR(date,'Day') AS dayname,
DATE_PART('week',date) AS week_iso,
DATE_PART('week',date + interval '1 day') AS week_alt
FROM dates
)
select date, dayname,
week_iso, week_alt, case when week_alt <> week_iso
then week_alt
else week_iso end as expected_week
from alt
order by date
Output:
date dayname week_iso week_alt expected_week
2014-01-01 Wednesday 1 1 1
2014-01-02 Thursday 1 1 1
2014-01-03 Friday 1 1 1
2014-01-04 Saturday 1 1 1
2014-01-05 Sunday 1 2 2
2014-01-06 Monday 2 2 2
2014-01-07 Tuesday 2 2 2
....
2017-01-01 Sunday 52 1 1
2017-01-02 Monday 1 1 1
2017-01-03 Tuesday 1 1 1
2017-01-04 Wednesday 1 1 1
2017-01-05 Thursday 1 1 1
2017-01-06 Friday 1 1 1
2017-01-07 Saturday 1 1 1
2017-01-08 Sunday 1 2 2
This query works perfectly replacing monday with sunday as the start of the week.
QUERY
SELECT CASE WHEN EXTRACT(day from '2014-01-05'::date)=4 AND
EXTRACT(month from '2014-01-05'::date)=1 THEN date_part('week',
'2014-01-05'::date) ELSE date_part('week', '2014-01-05'::date + 1)
END;
OUTPUT
date_part
-----------
2
(1 row)

How to get last 3 Months of "Monday to Sunday" dates In Redshift?

How can I get last 3 Months of "Monday to Sunday" dates in Redshift?
S.no Start_dt End_dt week
1 18-Jul-16 24-Jul-16 Week1
2 25-Jul-16 31-Jul-16 Week2
3 1-Aug-16 7-Aug-16 Week3
4 8-Aug-16 14-Aug-16 Week4
5 15-Aug-16 21-Aug-16 Week5
6 22-Aug-16 28-Aug-16 Week6
7 29-Aug-16 4-Sep-16 Week7
8 5-Sep-16 11-Sep-16 Week8
9 12-Sep-16 18-Sep-16 Week9
10 19-Sep-16 25-Sep-16 Week10
11 26-Sep-16 2-Oct-16 Week11
12 3-Oct-16 9-Oct-16 Week12
13 10-Oct-16 16-Oct-16 Week13
I've tried this:
select
trunc(date_trunc('week',sysdate)) st_dt,
trunc(date_trunc('week', sysdate)+6) ed_dt,
'week'||row_number() over (order by null) as week
but it only returns the current week's Monday and Sunday.
You can use generate_series() to generate a range of dates:
SELECT
trunc(day) as start_date,
trunc(day + 6) as end_date
FROM
(select date_trunc('week', sysdate) + (generate_series(1, 12) * interval '1 week') as day)
ORDER BY 1 ASC
This results in:
week start week end
2016-10-24 2016-10-30
2016-10-31 2016-11-06
2016-11-07 2016-11-13
2016-11-14 2016-11-20
2016-11-21 2016-11-27
2016-11-28 2016-12-04
2016-12-05 2016-12-11
2016-12-12 2016-12-18
2016-12-19 2016-12-25
2016-12-26 2017-01-01
2017-01-02 2017-01-08
2017-01-09 2017-01-15
Please note that generate_series() in Amazon Redshift cannot be joined with existing tables. It can only be used as a "Leader-only" query.

db2 - Get Week of the Month

Hello guys I need know the number of the week of a month
For example:
Date | WeekOfTheMonth
2015-04-15 | 3
2015-03-01 | 1
2015-01-08 | 2
Beacuse in docs only see Week of the year
Thanks
Test this SQL query
SELECT KURRENT - FIRSTY + 1 FROM ( -- AVOID CURRENT AND FIRST KEYWORD
SELECT
WEEK_ISO(DATE(1) + (YEAR(date_colum)-1) YEARS + (MONTH(date_colum)-1) MONTHS )AS FIRSTY ,
WEEK_ISO(date(date_column)) AS KURRENT
FROM TEST_DATE_TABLE
) AS T
Try this:
SELECT week_iso(current date) -
week_iso(last_day(current date) - 1 month + 1 day)
FROM sysibm.sysdummy1
You don't mention your platform, but VARCHAR_FORMAT has a W format string, which gives the week of the month:
Week of the month (1-5), where week 1 starts on the first day of the
month and ends on the seventh day.
SELECT VARCHAR_FORMAT(CURRENT TIMESTAMP, 'W') FROM SYSIBM.SYSDUMMY1