PostgreSQL - 如果相关条件不存在,则选择结果

时间:2013-08-23 11:17:00

标签: sql postgresql postgresql-9.2

在PostgreSQL中是否可以过滤行,以便在某个时间间隔内显示一个与其他表空行相关的表行。

换句话说,想象一下这个例子:

有两个表partnerscalls

create table partners(
    id int,
    name varchar(100),
    call_id references calls (id),
    PRIMARY KEY (id)
);

create table calls(
    id int,
    name varchar(100),
    date timestamp,
    PRIMARY KEY (id),
);

现在想象一下。在合作伙伴表中创建了一些行。一些调用和调用出现在调用中(调用时注册日期)。但我需要过滤相反的事情。如何查看没有电话的合作伙伴在2013-05-01和2013-06-01之间的日期?

我不明白的是如何在任何时间段内过滤不存在​​记录的合作伙伴(如果不需要时间段,那么这将很容易。我可以过滤没有呼叫的合作伙伴)?我需要使用外部时间吗?

3 个答案:

答案 0 :(得分:3)

类似的东西:

select p.*
from partners p
where not exists (select 1 
                  from calls c
                  where c.name = p.name 
                    and c.date between DATE '2013-05-01' and DATE '2013-06-01');

答案 1 :(得分:1)

你的架构对我来说很奇怪。为什么合作伙伴有参与呼叫?我会说它应该是这样的:

create table partners(
    id int,
    name varchar(100),
    PRIMARY KEY (id)
);

create table calls(
    id int,
    date datetime,
    partner_id references partners (id),
    PRIMARY KEY (id),
);

,您的查询就像

select p.*
from partners as p
where
    not exists
    (
        select *
        from calls as c
        where c.partner_id = p.id and c.date between '2013-05-01' and '2013-06-01'
    )

如果您想保留当前的架构,那么您的查询可以采用所有不同的合作伙伴名称,然后排除那些在给定时间段内有来电的人:

select distinct p.name
from partners as p
except
select distinct p.name
from partners as p
    inner join calls as c on c.id = p.call_id
where c.date between '2013-05-01' and '2013-06-01'

如果合作伙伴和调用之间没有链接,并且您只想从调用表中排除名称(我说,架构真的很奇怪:)

select distinct p.name
from partners as p
except
select distinct c.name
from calls as c
where c.date between '2013-05-01' and '2013-06-01'

答案 2 :(得分:0)

你有一个非常神秘的数据结构。名为partners的表每个伙伴应该有一行。你所谓的合作伙伴应该是另一张桌子。

因此,首先要做的是获取合作伙伴列表。然后使用left outer join连接到其他表。如果没有匹配,则保留行:

select p.*
from (select distinct name
      from partners
     ) as allpartners left outer join
     p
     on p.name = allpartners.name left outer join
     calls c
     on p.call_id = c.id and
        c.date between DATE1 and DATE2
where c.name is NULL;