架构:
CREATE TABLE "expenses_commissionrule" (
"id" serial NOT NULL PRIMARY KEY,
"country" varchar(2) NOT NULL,
"created" timestamp with time zone NOT NULL,
"modified" timestamp with time zone NOT NULL,
"activity" tsrange NOT NULL
);
Run Code Online (Sandbox Code Playgroud)
说明:
我想创建一个应用程序来管理佣金计算。每个规则都有活动期。每个国家都有一套独立的规则。
约束:
第一的。为避免歧义,这些活动期不应重叠。我做了以下约束:
ALTER TABLE expenses_commissionrule
ADD CONSTRAINT non_overlapping_activity
EXCLUDE USING GIST (country WITH =, activity WITH &&);
Run Code Online (Sandbox Code Playgroud)
第二。在任何时间点都应该只有一个佣金规则,因此表中的间隔之间不应存在间隙。换句话说,所有区间的总和应该是 -INF:+INF。
问题:如何添加第二个约束?用例:我们有一个无限期的规则。我想切换到新规则,该规则应从下个月开始。在这种情况下,我想将当前规则结束期设置为当月月底,并在单个操作中添加新规则。
更新:将来我想添加以下行为:
换句话说,所有先前的约束都应仅应用于 user_id 为 NULL 的行。如何做到这一点?
PostgreSQL …
我想生成给定日期的通用季度结束日期。
例如:如果我有2010-01-01
,我想返回2010-03-31
,等等。
我可以得到季度号和年份:
select to_char(date_trunc('quarter', current_date)::date, 'yyyy-q');
Run Code Online (Sandbox Code Playgroud)
2017-3
从今天起返回的是2017-07-14
我如何很好地获得季度结束日期?
我可以得到答案,但它非常丑陋:
select to_char(date_trunc('year', date '2015-01-01'),'yyyy') || '-' ||case
when (select extract('quarter' from date_trunc('quarter', date '2015-01-01')::date )) = 1 then '03-31'
when (select extract('quarter' from date_trunc('quarter', date '2015-01-01')::date )) = 2 then '06-30'
when (select extract('quarter' from date_trunc('quarter', date '2015-01-01')::date )) = 3 then '09-30'
when (select extract('quarter' from date_trunc('quarter', date '2015-01-01')::date )) = 4 then '12-31'
else '?'
end
Run Code Online (Sandbox Code Playgroud)
返回2015-03-31
因为我把2015-01-01
。
有没有更好的办法?
上下文正在从其余服务器连接到 Postgres 数据库。
考虑一个假设的代表性示例:我希望能够获取帐户创建日期比任意值早/新的名称列表。
在下面的示例查询中,表结构很简单 -name
是 type text
,并且creation_date
是 type timestamp
。所以当我做类似的事情时
server_pg_module:query("select name from new_table where
current_timestamp - creation_date < '6 days'")
Run Code Online (Sandbox Code Playgroud)
它工作得很好。但我真正想做的是6 days
从服务器获取该值。所以我尝试像
server_pg_module:query("select name from new_table where
current_timestamp - timestamp < $1", ["6 days"]
Run Code Online (Sandbox Code Playgroud)
它抛出一个错误。我试过'6 days'
,"'6 days'"
以及其他一些混合物,都抛出错误。所以为了检查我添加了一个新interval
的类型列interval
并尝试了一个查询
server_pg_module:query("insert into new_table (name, interval) values ($1, '3 day')", ["fooo"]).
Run Code Online (Sandbox Code Playgroud)
哪个有效,但是
server_pg_module:query("insert into new_table (name, interval) values ($1, $2)", ["fooo", "3 days"]).
Run Code Online (Sandbox Code Playgroud)
休息。为了更好的衡量,除了"'3 days'"
上面提到的混合物之外,我还尝试过 …
我有一个表,其中存储了一个活动列表,其时间间隔由 2 个日期分隔。
样本:
+------+---------------------+---------------------+-------------+
| name | start | end | time (calc) |
+------+---------------------+---------------------+-------------+
| me | 2017-04-03 11:00:00 | 2017-04-03 11:30:00 | 30 |
| me | 2017-04-03 23:45:00 | 2017-04-04 00:15:00 | 30 |
| me | 2017-04-04 10:00:00 | 2017-04-04 11:00:00 | 60 |
| me | 2017-04-04 10:30:00 | 2017-04-04 11:30:00 | 60 |
| me | 2017-04-05 23:00:00 | 2017-04-05 23:30:00 | 30 |
| me | 2017-04-05 23:15:00 | 2017-04-07 00:45:00 | …
Run Code Online (Sandbox Code Playgroud) 例子:
INTERVAL '5 minute'
,则所需输出为 2018-05-17 22:50:00。INTERVAL '10 minute'
,则所需输出为 2018-05-17 22:50:00。INTERVAL '1 hour'
,则所需的输出为 2018-05-17 23:00:00。INTERVAL '1 day'
,那么期望的输出是 2018-05-18 00:00:00。我的问题与这个问题类似,但(我认为)有足够大的差异。我有一个基本范围,我想在一个表中找到所有其他范围与它和彼此冲突。或者更确切地说是形成范围的项目,但它并没有真正产生影响。
带星号的那一行是起始范围。范围 1,2 和 3 是应该扩展它的范围。结果范围应该是 X。
1 |
3 | ===1==== ====
5 | ==2== ====*==== ====
6 | ====3==== =====
--+-------------------------------------
| |<--------X-------->|
Run Code Online (Sandbox Code Playgroud)
我写过这个:
WITH cte
AS (
SELECT DATA1.ID, DATA1.STARTDATE, DATA1.ENDDATE
FROM DATA1
WHERE
DATA1.ID = @PARID AND
DATA1.STARTDATE > @STARTDATE AND
DATA1.ENDDATE < @ENDDATE
UNION ALL
SELECT DATA1.ID, DATA1.STARTDATE, DATA1.ENDDATE
FROM cte
INNER JOIN DATA1 ON (DATA1.ID = cte.ID)
WHERE
DATA1.ID = @PARID AND
(cte.STARTDATE < DATA1.ENDDATE AND cte.ENDDATE > DATA1.ENDDATE)
) …
Run Code Online (Sandbox Code Playgroud) 我经常遇到以下问题。我有两张间隔表。它们受日期限制(没有时间部分)。每个表中的间隔不重叠。
开始时间 | 结束时间 |
---|---|
2015-01-03 | 2015-03-02 |
2015-03-05 | 2015-04-01 |
开始时间 | 结束时间 |
---|---|
2015-01-07 | 2015-02-27 |
2015-03-01 | 2015-03-13 |
2016-01-01 | 2016-01-02 |
我想找到两个表的集合差异,即代表第一个表中而不是第二个表中的时间的间隔。
上面的虚拟示例所需的输出:
开始时间 | 结束时间 |
---|---|
2015-01-03 | 2015-01-06 |
2015-02-28 | 2015-02-28 |
2015-03-14 | 2015-04-01 |
即,如果第一个表的日期在下面用黄色标记,并且第二个表的范围用框包围,我将寻找未装箱的黄色日期的连续范围。
我目前将两端都视为包含间隔,并使用 DateTime 作为时间戳。我当前的方法是通过三重自连接(恶心)获取第二个表的补集,然后通过连接将结果与第一个表相交。不好玩。
有更好的方法吗?
我在 PostgreSQL 13 中有这个表:
CREATE TABLE public."domain" (
id int8 NOT NULL GENERATED ALWAYS AS IDENTITY,
domain_name varchar NOT NULL,
-- more columns
expire_date timestamp NULL,
days_before_trigger int4 NOT NULL DEFAULT 14
);
Run Code Online (Sandbox Code Playgroud)
现在我想添加一个生成的列notify_trigger_date
,派生自expire_date
减days_before_trigger
,以记录我的网站 url ssl 证书到期日期。如何自动生成该列?
它看起来像这样:
notify_trigger_date = expire_date - 7 day
Run Code Online (Sandbox Code Playgroud)
我正在尝试像这样实现它:
ALTER TABLE "domain" ADD COLUMN notify_trigger_date timestamp
GENERATED ALWAYS AS ((expire_date::timestamp - '1 day')) STORED;
Run Code Online (Sandbox Code Playgroud)
我不知道如何1 day
用天数替换days_before_trigger
?此命令运行时出错:
Run Code Online (Sandbox Code Playgroud)SQL Error [22007]: ERROR: invalid input syntax for …
interval ×8
postgresql ×5
datetime ×3
sql-server ×2
constraint ×1
datatypes ×1
date ×1
date-math ×1
functions ×1
mysql ×1
parameter ×1
query ×1