tl;博士
从 start_date >= now 和 is_monday = true 的通知中选择 *
SELECT *
FROM event_
WHERE
when_ >= DATE '2018-01-22'
AND
EXTRACT( isodow FROM when_ ) -- Access portion of date-value in the `isodow` field meaning the day-of-week as defined by the ISO 8601 standard.
= 2 -- 2 = Tuesday in ISO 8601 definition of a week.
;
如果要检查多个星期几的值,请使用数组。
SELECT *
FROM event_
WHERE
when_ >= DATE '2018-01-22'
AND
EXTRACT( isodow FROM when_ ) -- Access portion of date-value in the `isodow` field meaning the day-of-week as defined by the ISO 8601 standard.
=
ANY( ARRAY[ 2 , 3 , 4 ] ) -- Define numbers for day-of-week per ISO 8601 where Monday-Sunday is 1-7.
;
详情
存储星期几的最佳方式
不要。
正如Answer by Barbaros Özhan 中所建议的那样,除了日期之外还存储星期几是多余的,因此违反了规范化。
Postgres 提供EXTRACT 函数来返回一个值(一个“字段”),代表日期时间值的某些方面。 Ingres 样式的等效项也可用,date_part。
Postgres offers two fields 确定星期几:
我建议你坚持第一个,标准定义。
让我们使用它们。
首先,找个日期。
SELECT DATE '2018-01-23' ;
2018-01-23
获取该日期的星期几。
SELECT EXTRACT ( isodow FROM DATE '2018-01-23' ) ;
返回一个双精度数值 2,表示星期二。
2
在array 中定义您的目标星期几值。例如,周二-周三-周四,ISO 8601 星期编号中的 2-4。
ARRAY[ 2 , 3 , 4 ]
询问数组是否包含某个数字。
SELECT ARRAY[ 2 , 3 , 4 ] @> ARRAY[ 2 ] ;
是的
或者,获得相同结果的另一种方法。
SELECT 2 = ANY ( ARRAY[ 2 , 3 , 4 ] ) ;
是的
在该声明中应用某个日期。
SELECT EXTRACT ( isodow FROM DATE '2018-01-23' ) = ANY ( ARRAY[ 2 , 3 , 4 ] ) ;
是的
我们可以把所有这些放在一起。我们将创建一个表,插入 3 行,然后进行查询。我们预计我们的第 2 行和第 3 行可以找到 ISO 8601 星期 2-4,而 1 月 22 日的第 1 行是星期一(第 1 天),应该省略。
DROP TABLE IF EXISTS event_
;
CREATE TABLE IF NOT EXISTS event_ (
pkey_ INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY ,
when_ DATE NOT NULL
);
INSERT INTO event_ ( when_ )
VALUES ( DATE '2018-01-22' ) , ( DATE '2018-01-23' ) , ( DATE '2018-01-24' )
;
SELECT * FROM event_
WHERE EXTRACT( isodow FROM when_ ) = ANY( ARRAY[ 2 , 3 , 4 ] )
;
运行时,果然第一行省略了。
2“2018-01-23”
3“2018-01-24”
在 x86_64-apple-darwin 上使用 pgAdmin 3.5 和 PostgreSQL 11.0 进行演示,由 Apple LLVM 版本 6.0 (clang-600.0.54)(基于 LLVM 3.5svn)编译,64 位。
存储星期值列表
你的问题不是很清楚。
也许您还问如何存储每周 7 天值中的哪一个是每个用户的偏好。
首先为一周中的 7 天值定义一个枚举。这提供了类型安全并确保了有效值。
CREATE TYPE ISO_DOW_ AS ENUM (
'MONDAY' , 'TUESDAY' , 'WEDNESDAY' , 'THURSDAY' , 'FRIDAY' , 'SATURDAY' , 'SUNDAY'
) ;
定义一个表来存储用户偏好。我们添加一个数组类型的列,一个整数数组。
CREATE TABLE user_pref_ (
pkey_ INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY ,
dows_ ISO_DOW_[] NOT NULL -- User can select 0, 1, or up to 7 day-of-week values to be used for searching notifications.
) ;
请务必使用 Postgres 中漂亮的 COMMENT 功能来记录我们的意图。我将把它作为练习留给读者。
插入一些行。
INSERT INTO user_pref_ ( dows_ )
VALUES ( ARRAY[]::ISO_DOW_[] ) , ( ARRAY[ 'TUESDAY' , 'WEDNESDAY' , 'THURSDAY' ]::ISO_DOW_[] ) , ( ARRAY[ 'FRIDAY' ]::ISO_DOW_[] )
;
最后一步,我还不能完全完成。我还没有确定在子查询中检索数组以传递给外部查询的ANY 函数的方法。应该是这样的:
SELECT * FROM event_
WHERE EXTRACT( isodow FROM when_ ) = ANY(
SELECT dows_ FROM user_pref_ WHERE pkey_ = 2 ;
) ;