sql查询提取新记录

时间:2014-10-27 23:50:30

标签: sql postgresql exists

我有以下表格:

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,应该是什么查询?

2 个答案:

答案 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值,则返回NULLNULL(&#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(对于在日期之前添加商品的公司,不会退还任何公司。)