Python postgres介绍如何为枚举数组中的每个值具体化一行

Python postgres介绍如何为枚举数组中的每个值具体化一行,python,postgresql,sqlalchemy,Python,Postgresql,Sqlalchemy,我有一个postgres表,用于存储定期约会,称为约会。我还有一个枚举类型,称为周中的日 周中的第天是一个枚举,如下所示: select enum_range(null::ck_day_of_week); 返回 {Monday,Tuesday,Thursday,Sunday,Saturday,Friday,Wednesday} “约会”表的DDL为: create table appointments ( id serial primary key not null, tit

我有一个postgres表,用于存储定期约会,称为约会。我还有一个枚举类型,称为周中的日

周中的第天是一个枚举,如下所示:

select enum_range(null::ck_day_of_week);
返回

{Monday,Tuesday,Thursday,Sunday,Saturday,Friday,Wednesday}
“约会”表的DDL为:

create table appointments
(
    id serial primary key not null,
    title varchar not null
    recurrence_start_date timestampz not null,
    recurrence_end_date timestampz,
    recurrence_days_of_week _ck_day_of_week  -- this is actually an array of enums, not just an enum. I don't fully understand why the DDL looks like this
);
质疑

select id, title, recurrence_days_of_week from appointments where recurrence_start_date <= now() and (recurrence_end_date is null or recurrence_end_date >= now());
我的问题是,我需要将这个结果“具体化”为UI视图的一组行。具体来说,我希望查询数据库并让它返回如下行:

id,My Recurring Appointment,date
其中,唯一键可能是约会id和特定日期,而日期基本上是重复性\开始\日期+周中日的组合。周中日的偏移量介于0和6之间

在postgres中,如何从包含枚举数组的列的表中进行选择,并让它为数组中的每个枚举值返回一行-virtual-single-row-of-real-same?我正在考虑一个视图或其他东西,但我现在确定如何编写select语句

如果这可以转化为SQLAlchemy,则会获得额外的积分


我也很开放,并考虑只创建一个约会表来存储每个约会的具体日期。但如果我这样做……理论上,对于没有结束日期的重复日期约会,表可能会无限大,所以我一直在努力避免这种情况。

首先,我不建议使用id作为列名

其次,我会使用内置的日期/时间函数来实现第一个目标。更具体地说,将提取函数与道琼斯指数参数day of week相结合,并使用生成_系列函数

确保在参考资料部分选中小提琴

查询每周每天的约会返回列表:

create or replace function fnc_appointment_list_dow_by_id(_app_id int)
    returns table (__app_id int, __title varchar, __recurrence_start_date timestamptz, __recurrence_appointment_day timestamptz, __reccurence_dow_offset int) as
$body$
        select
                app.app_id,
                app.app_title,
                app.app_recurrence_start_date,
                _appointment_days._day,
                extract(dow from _day)::int
            from
                appointments app,
                generate_series(app.app_recurrence_start_date, app.app_recurrence_end_date, interval '1 day') _appointment_days(_day)
            where app.app_id=_app_id;
$body$
    language sql stable; -- consider changing function volatility as needed.

-- select * from fnc_appointment_list_dow_by_id(1);
查询返回每周约会天数数组:

create or replace function fnc_appointment_array_dow_by_id(_app_id int)
        returns table (__app_id int, __title varchar, __recurrence_start_date timestamptz, __recurrence_appointment_day timestamptz[], __reccurence_dow_offset int[]) as
    $body$
        select
                app.app_id,
                app.app_title,
                app.app_recurrence_start_date,
                array_agg(_day::timestamptz),
                array_agg(extract(dow from _day)::int)
            from
                appointments app,
                generate_series(app.app_recurrence_start_date, app.app_recurrence_end_date, interval '1 day') as _appointment_days(_day)
            where app.app_id=_app_id
            group by app.app_id, app.app_title, app.app_recurrence_start_date;
    $body$
        language sql stable; -- consider changing function volatility as needed.

-- select * from fnc_appointment_array_dow_by_id(1);
如果这两项功能中的任何一项是您想要的,请告诉我,我们可以继续实现下一个目标

参考资料:

寻找提取物 作用 寻找 生成带有时间戳类型参数的_系列函数 不要介意timestamptz数组显示为int数组
非常感谢您如此有帮助的回复。这实际上把我带到了我需要的地方,尽管-我想-它有点绕过了我拥有的数组枚举列。不过,我需要做的第一件事是为每项活动取消{星期一、星期二、星期四、星期天、星期六、星期五、星期三}。一旦我有了它,我就能够使用你提到的概念,比如提取和生成_序列来生成复发。很高兴你找到了它。干杯
create or replace function fnc_appointment_array_dow_by_id(_app_id int)
        returns table (__app_id int, __title varchar, __recurrence_start_date timestamptz, __recurrence_appointment_day timestamptz[], __reccurence_dow_offset int[]) as
    $body$
        select
                app.app_id,
                app.app_title,
                app.app_recurrence_start_date,
                array_agg(_day::timestamptz),
                array_agg(extract(dow from _day)::int)
            from
                appointments app,
                generate_series(app.app_recurrence_start_date, app.app_recurrence_end_date, interval '1 day') as _appointment_days(_day)
            where app.app_id=_app_id
            group by app.app_id, app.app_title, app.app_recurrence_start_date;
    $body$
        language sql stable; -- consider changing function volatility as needed.

-- select * from fnc_appointment_array_dow_by_id(1);