我有以下表格:
CREATE TABLE Company (
CompanyUniqueID BIGSERIAL PRIMARY KEY NOT NULL,
Name VARCHAR (150) NOT NULL
);
CREATE TABLE Item (
ItemUniqueID BIGSERIAL PRIMARY KEY NOT NULL,
CompanyUniqueID BIGINT NULL REFERENCES company DEFERRABLE INITIALLY DEFERRED,
Name VARCHAR (150) NOT NULL,
AddedDate TIMESTAMP without time zone DEFAULT now()
);
在应用程序的生命周期中,新公司和项目被添加到表中。 我希望创建一个SQL查询,它将从给定日期选择“新添加的公司” 我已经开始使用此查询:
(Select * from company
where companyuniqueid in (
select distinct companyuniqueid from Item where AddedDate > '2014-10-25'))
以上情况并不好,因为在2014-10-25之后添加并属于已经存在的公司的项目也将被选中。
例如,2014-10-20中Company
表的快照可能如下所示:
1 AAA
2 BBB
3 CCC
和表项看起来像:
1 1 111 2014-10-01
2 2 222 2014-10-10
3 2 333 2014-10-10
4 3 444 2014-10-15
在2014-10-26上增加了以下记录:
表公司
4 DDD
表项目
5 1 555 2014-10-26
6 3 663 2014-10-26
7 4 777 2014-10-27
我已尝试将其添加到查询中:
(Select * from company
where companyuniqueid in (
select distinct companyuniqueid from Item
where AddedDate > '2014-10-25')
and companyuniqueid not in (
select distinct companyuniqueid from Item
where AddedDate <= '2014-10-25'))
但是我得到一个空的结果,为了只接收4个DDD,应该是什么查询?
答案 0 :(得分:2)
使用EXISTS
反半连接。通常比NOT IN
更快,更干净:
SELECT *
FROM company c
WHERE NOT EXISTS (
SELECT 1
FROM item
WHERE addeddate < '2014-10-25'
AND companyuniqueid = c.companyuniqueid);
返回
在指定日期之前没有任何项目的公司。
包括没有物品的公司,也可能包括addeddate IS NULL
的物品
要将结果限制为具有新项目的公司,请添加:
WHERE EXISTS (
SELECT 1
FROM item
WHERE addeddate >= '2014-10-25'
AND companyuniqueid = c.companyuniqueid)
但请考虑在表added_date
中添加另一列company
,以避免含糊不清并简化操作。
可能是 NOT IN
的另一个案例,其中包含NULL
值的集合。
您的专栏item.companyuniqueid
允许NULL
个值。你的子查询:
select distinct companyuniqueid from Item where AddedDate <= '2014-10-25'
...可能包含NULL
值。在这种情况下,此表达式永远不会是TRUE
:
companyuniqueid not in (<above subquery>)
如果集合包含FALSE
值,则返回NULL
或NULL
(&#34;未知&#34;)。但只有TRUE
符合WHERE
条件。所以没有返回任何行。
Note that the same is not true for an empty set.如果上面的子查询会返回 no row ,那么NOT IN
表达式将评估为TRUE
,只要左侧为NOT NULL
}。
基本上,尽可能避免NOT IN (<subquery>)
。 NOT EXISTS
几乎总是优越的
如果您使用它,请了解NULL
值。更多细节:
答案 1 :(得分:1)
with min_added as
(
select i.companyuniqueid, min(i.addeddate) as addeddate
from item i
group by companyuniqueid
)
select * from min_added where min_added.addeddate > '2014-10-26';
将为所有在指定日期之后添加商品的公司提供公司ID(对于在日期之前添加商品的公司,不会退还任何公司。)