我有这种情况。 我有客户,我有电话 我想知道,如果一个客户每个日期至少有1个电话,如果他/她没有,我想要一个没有电话的日期数组。
客户端 id名称 1罗伯特 2 nidia
呼叫 id date id_client 1 2015-01-01 2 2 2015-01-31 1
ID客户端1最近没有呼叫2015-01-01
你知道吗?答案 0 :(得分:0)
首先,必须有一些机制来确定查询检查的日期。理论上有一个无限数量的日期,在此期间,给定的客户可能不已拨打任何电话!您必须查询该无穷大的子集。
如果您在查询中使用硬编码确定需要检查的少量日期,那么我认为这是您正在寻找的内容:
drop table if exists call;
drop table if exists client;
create table client (id int, name varchar(32), primary key (id) );
insert into client (id,name) values (1,'robert'), (2,'nidia');
create table call (id int, d date, client_id int references client(id), primary key (id) );
insert into call (id,d,client_id) values (1,'2015-01-01',(select id from client where name='nidia')), (2,'2015-01-31',(select id from client where name='robert'));
select
cl.name,
array_agg(ds.d) no_call_dates
from
client cl
cross join (select '2015-01-01'::date d union all select '2015-01-15' union all select '2015-01-31') ds
left join call ca on ca.client_id=cl.id and ca.d=ds.d
where
ca.id is null
group by
cl.name
;
输出:
name | no_call_dates
--------+-------------------------
nidia | {2015-01-31,2015-01-15}
robert | {2015-01-15,2015-01-01}
(2 rows)
我已经硬编码并将三个日期合并为单列"表格文字" (如果愿意的话)并使用client
表交叉加入,导致每个客户端每行一行。然后,该结果集可以与客户端ID和呼叫日期上的call
表保持连接。然后,您可以使用where
子句仅过滤call
表无法加入的行,这会产生无通话天数的结果集,仍然是每个客户端的日期。然后,您可以按客户端进行分组,并使用array_agg()
聚合函数构建客户端不进行调用的日期数组。
如果您不想对日期进行硬编码,您可以提前准备一份日期表,并从cross join
子句中选择,或者选择{中定义的所有日期{1}} table(call
),或者使用一些更复杂的逻辑来选择要检查的日期。在所有这些情况下,您只需替换"表格文字"使用适当的子查询。
编辑:是的,这非常可行。您可以使用generate_series()
函数生成整数序列并将其添加到固定的开始日期,从而生成日期范围。如前所述,这可以在交叉连接子查询中完成。避免重复的好方法是使用CTE设置开始和结束日期:
select distinct d from call;
输出:
select
cl.name,
array_agg(ds.d order by ds.d) no_call_dates
from
client cl
cross join (with dr as (select '2015-01-01'::date s, '2015-01-31'::date e) select s+generate_series(0,e-s,15) d from dr) ds
left join call ca on ca.client_id=cl.id and ca.d=ds.d
where
ca.id is null
group by
cl.name
;
在上面的查询中,我使用1月1日到1月31日的日期范围生成三个日期,2015-01-01,2015-01-16和2015-01-31,增量为15.显然对于你的情况,你可能想要增加一个,但我只用了15个只有三个日期的简单例子。
此外,我在 name | no_call_dates
--------+-------------------------
nidia | {2015-01-16,2015-01-31}
robert | {2015-01-01,2015-01-16}
(2 rows)
电话中添加了order by
条款,因为按日期排序可以更好,而非随机。