Reputation: 847
I have a table with the weekday stored as an integer, 0 to 6.
What function do I need to create the day names relative to these day numbers?
Eg: 0 -> Sun, 1->Mon, etc
Like:
SELECT magic(my_day_number) FROM my_table;
Mon
Upvotes: 4
Views: 8658
Reputation: 1
Supports locale as well as built in day name formats and is the shortest...
to_char('9/9/2001'::date + day_number, 'Dy')
(9/9/2001 or any given Sunday)
Example:
SELECT to_char('9/9/2001'::date + my_day_number, 'Dy')
FROM generate_series(0,6) AS my_table(my_day_number);
Sun
Mon
Tue
Wed
Thu
Fri
Sat
Upvotes: 0
Reputation: 51
That's what I would use:
select ('{Sun,Mon,Tue,Wed,Thu,Fri,Sat}'::text[])[extract(dow from now()) + 1] as day_of_week;
Or if you prefer a function:
CREATE OR REPLACE FUNCTION dow_name(p_index integer)
RETURNS text LANGUAGE sql STRICT IMMUTABLE PARALLEL SAFE AS
$$
SELECT (array['Sun','Mon','Tue','Wed','Thu','Fri','Sat'])[p_index + 1];
$$;
Both options with '{...}'::text[]
and array[...]
work 8% faster (on Postgres 12) comparing to using CASE
block.
Upvotes: 5
Reputation: 1778
The other answers are good, but honestly I'd recommend doing this at the app layer, not in the database.
Formatting to a day name does not improve normalization or query speed, so arguably does not belong in the database. But if you insist on using the database layer for this, an immutable function is probably the way to go.
CREATE OR REPLACE FUNCTION day_name(day_index integer)
RETURNS text LANGUAGE sql STRICT IMMUTABLE PARALLEL SAFE AS $$
SELECT CASE day_index
WHEN 0 THEN 'Sun'
WHEN 1 THEN 'Mon'
WHEN 2 THEN 'Tue'
WHEN 3 THEN 'Wed'
WHEN 4 THEN 'Thu'
WHEN 5 THEN 'Fri'
WHEN 6 THEN 'Sat'
END;
$$;
I called the function day_name
to be more descriptive, and hopefully the way it's implemented does not appear to be magic. By making the function IMMUTABLE
, once the database calculates it once, it can use a cached result, dramatically improving speed over an ad hoc single-use query.
Upvotes: 1
Reputation: 17906
Postgres can return this information for dates.
You can transform these days into dates, then extract the day name. It has the benefit of allowing changing language.
The year 2017 is used because January 1st is a Sunday (day 0) and the format IDDD
considers day 1 as the 1st Monday of the year.
WITH myTable(my_day_number) as (values (0),(1),(2),(3),(4),(5),(6))
SELECT to_char(to_date(my_day_number||'-2017','IDDD-IYYY'), 'Day')
FROM mytable;
to_char
-----------
Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
Upvotes: 2
Reputation: 222702
A simple and efficient method uses case
instead of date manipulation routines:
select case my_day_number
when 0 then 'Sun'
when 1 then 'Mon'
when 2 then 'Tue'
...
when 6 then 'Sat'
end my_day_name from mytable
Upvotes: 2