前一天大家经过一段编码展现了怎么根据Python的Pandas包生成一个日历表,假如诸位有兴趣可以参照:根据Pandas生成日历表;
不得不说在 DB Engine(
https://db-engines.com/en/ranking)排名榜中,PostgreSQL最近几年一直都很平稳,而且在每个云服务平台里都有十分完善的PaaS商品供每个公司使用,那麼大家现在的目的便是演试一下怎样根据#postgresql#来生成相近的日历表。
文中采用的PostgreSQL版本号为14.1,Windows Server 2016自然环境下运作。
DB Engine Ranking
一些主要的作用
GENERATE_SERIES
在进行解决方法以前,大家先掌握PostgreSQL的一个函数公式:“GENERATE_SERIES”,根据字面意思应当能大概猜到,这一函数公式可以生成一个序列的数据信息,直接讲便是生成列项的一个数据分析表。
大家先根据psql指令获得针对此函数公式的叙述,如下图所示:
GENERATE_SERIES Description in psql
此函数公式关键有几个特性:
- 可以返回整形(bigint,int),浮点数类型(numeric)序列;
- 可以返回带时区时间的时间格式类型(timestamp)序列;
- 可以返回没有时区时间的时间格式类型(timestamp)序列;
简易举例说明:
1.1 返回整形序列
- 当特定起点,终点站主要参数
SELECT GENERATE_SERIES(1, 10);
結果如下所示所显示:
返回整形序列
- 当特定起点,终点站,步幅主要参数
步幅可以解释为弹跳值,从1逐渐,假如步幅为2,那麼下一个数据应该是1 2 = 3,依此类推;
SELECT GENERATE_SERIES(1, 10, 2);
返回整形序列,特定步幅
1.2 返回浮点数类型序列
此作用类似返回整形序列,不同之处是传到的可以是带小数位的浮点数类型数据信息,如下图所示:
SELECT GENERATE_SERIES(1.1, 10.9, 0.5);
返回浮点数类型序列,特定步幅
1.3 返回时间格式(timestamp)序列
此功用可以根据特定起点,终点站和步幅三个主要参数,返回一段时间戳的序列数据信息,如下图所示:
SELECT GENERATE_SERIES(\'2022-01-01\'::TIMESTAMP, \'2022-01-31\'::TIMESTAMP, \'1 DAY\') AS datum;
返回时间格式序列
必须留意的是:
- 务必与此同时特定三个主要参数,起点,终点站,步幅;
- 起点和终点站主要参数,务必是时间格式类型(timestamp),假如传到的是日期类型,必须表明变换;
- 步幅可以是钟头,分鐘,秒,天,礼拜,年等;
日期类型数据信息实际操作
大家必须记牢这一个实际操作:日期 整数金额 = 日期,如下边事例所显示:
date integer → date
Add a number of days to a date
date \'2022-01-09\' 5 → 2022-01-14
Case 1: 当月测算
Case 2: 跨月计算
下边大家融合GENERATE_SERIES 函数公式完成怎样获得一个日期类型的序列;
起点:2022-01-01, 终点站:2022-01-31;这两个时间点正中间间距了30天,根据编码完成如下所示:
SELECT \'2022-01-01\'::DATE s.a AS datum
FROM GENERATE_SERIES(0, 30) AS s(a);
結果如下图所示:
根据GENERATE_SERIES函数公式返回日期类型序列
这类计划方案的优点是:
- 返回日期类型序列,原函数仅适用传到时间格式类型数据信息;
- 不用按日期時间的Interval特定间隔时间,将时间间隔默认设置为1天。
自定义函数
根据以上的训练,大家已经可以根据传到逐渐日期和间距日数获得大家需要的結果。但是假如业务流程上常常转换逐渐日期和间隔时间,大家还要持续的重新写过SQL句子。为了防止再次改变SQL句子,大家将界定一个函数公式“get_calendar”,并将“逐渐日期”(start_dt)和“间隔时间”(days)作为主要参数传到,进而使人们的效果和句子更为灵便。
编码如下所示所显示:
CREATE OR REPLACE FUNCTION public.get_calendar(
start_dt date,
days integer)
RETURNS TABLE(datum date)
LANGUAGE \'sql\'
AS $BODY$
SELECT start_dt s.a AS datum
FROM GENERATE_SERIES(0, days) AS s(a)
GROUP BY s.a
ORDER BY 1;
$BODY$;
简易测试一下,仍然将‘2022-01-01’做为逐渐日期,间隔时间设定为30天:
SELECT * FROM get_calendar(\'2022-01-01\', 30);
自定义函数让编码更为灵便
详细编码完成
最后,大家将根据PostgreSQL的很多日期和字符串数组变换函数公式,拓展人们的自定义函数“get_calendar”,获得一个完全的日历表,实际编码如下所示所显示。
/* Author: Derek Zhu
Date: 2022-01-08
Purpose: Calendar table practice in PostgreSQL 14.1
Description:
Start date: 2022-01-01
Set days length in 2nd argument of \'Genarate_series\' function */
-- FUNCTION: public.get_calendar(date, integer)
-- DROP FUNCTION IF EXISTS public.get_calendar(date, integer);
CREATE OR REPLACE FUNCTION public.get_calendar(
start_dt date,
days integer)
RETURNS TABLE(datum date, year numeric, month numeric, day_of_month numeric, week_of_year numeric, iso_day_of_week numeric, year_calendar_week text, day_of_year numeric, quarter_of_year numeric, quartal text, year_quartal text, day_name text, month_name text, year_month text, year_half integer, leap_year boolean, weekend text, cw_start date, cw_end date, month_start date, month_end date)
LANGUAGE \'sql\'
COST 100
VOLATILE PARALLEL UNSAFE
ROWS 1000
AS $BODY$
SELECT
datum,
EXTRACT(YEAR FROM datum) AS \"year\",
EXTRACT(MONTH FROM datum) AS \"month\",
EXTRACT(DAY FROM datum) AS day_of_month,
EXTRACT(WEEK FROM datum) AS week_of_year,
-- ISO 8601 day of the week numbering, The day of the week as Monday (1) to Sunday (7)
EXTRACT(ISODOW FROM datum) AS iso_day_of_week,
-- Standard Gregorian day of the week numbering, The day of the week as Sunday (0) to Saturday (6)
-- EXTRACT(DOW FROM datum) AS day_of_week,
-- ISO calendar year and week
TO_CHAR(datum, \'iyyy/IW\') AS year_calendar_week,
EXTRACT(DOY FROM datum) AS day_of_year,
EXTRACT(QUARTER FROM datum) AS quarter_of_year,
\'Q\' || TO_CHAR(datum, \'Q\') AS quartal,
TO_CHAR(datum, \'yyyy/\"Q\"Q\') AS year_quartal,
TO_CHAR(datum, \'TMDay\') AS day_name,
TO_CHAR(datum, \'TMMonth\') AS month_name,
TO_CHAR(datum, \'yyyy/mm\') AS year_month,
-- Half year
CASE WHEN EXTRACT(MONTH FROM datum) < 7 THEN 1 ELSE 2 END AS year_half,
-- Leap year
CASE WHEN EXTRACT(YEAR FROM datum) % 4 = 0 THEN TRUE ELSE FALSE END AS leap_year,
-- Weekend
CASE WHEN EXTRACT(ISODOW FROM datum) in (6, 7) THEN \'Weekend\' ELSE \'Weekday\' END AS weekend,
-- ISO start and end of the week of this date
datum (1 - EXTRACT(ISODOW FROM datum))::integer AS cw_start,
datum (7 - EXTRACT(ISODOW FROM datum))::integer AS cw_end,
-- Start and end of the month of this date
datum (1 - EXTRACT(DAY FROM datum))::integer AS month_start,
((datum (1 - EXTRACT(DAY FROM datum))::integer \'1 month\'::interval)::date - \'1 day\'::interval)::DATE AS month_end
FROM (
SELECT start_dt s.a AS datum
FROM GENERATE_SERIES(0, days) AS s(a)
GROUP BY s.a
) AS calendar
ORDER BY 1;
$BODY$;
ALTER FUNCTION public.get_calendar(date, integer)
OWNER TO postgres;
获得2022年全年度日历,如下所示所显示:
SELECT * FROM get_calendar(\'2022-01-01\', 364);
2022 Calendar Table
根据文本编辑观查結果,如下所示所显示:
Calendar data in csv
根据Excel观查結果,如下所示所显示:
Calendar data in excel
至此,大家已经完成了全部作用;
汇总
根据PostgreSQL转化成日历表关键有下边好多个特别注意点:
- ISO8601规范中,一个星期的时间为:Monday (1) ~ Sunday (7);
- 了解并灵巧运用GENERATE_SERIES函数公式转化成日期编码序列;
- 培养模块化设计思维模式,将常用的数据信息实际操作抽象化为函数公式或方式,可以拓展运用范畴;
与前日根据Python Pandas的例子一样,大家最后也将解决方法抽象化为一个函数公式,供中后期灵便启用,尽管传到的主要参数和最后的結果不完全一致,可是总体策略是相似的。
想对自己说的话
PostgreSQL 现阶段在许多公司都是在很多应用,根据PG群集构建数据库管理服务平台也是许多公司近几年来在尽力做的完成,去IOE早就实行很多年,应用开源项目更换商业手机软件也是必然趋势,PG应当被关注起來,针对PG的一些普遍和主要的实际操作,也需要应当记熟我心。
对于MySQL和PG选哪个这类神仙打架的事儿,真没空想那么多,纯开源系统,或是PG吧~
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。