SQL查询来提取新记录(sql query to extract new records)

2019-10-21 04:20发布

我有以下表格:

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日之后,并将属于已经存在的企业的项目也将被选中。

例如,快照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?

Answer 1:

使用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_datecompany ,以避免歧义和简化的东西。

为什么原始查询不工作?

大概另一种情况NOT IN与含一组NULL
你列item.companyuniqueid允许NULL值。 您的子查询:

select distinct companyuniqueid from Item where AddedDate <= '2014-10-25'

...大概包括NULL值。 在这种情况下,这种表达是从未TRUE

companyuniqueid not in (<above subquery>)

返回FALSENULL (“未知”)如果该组包括一个NULL值。 但是,只有TRUE将有资格作为WHERE条件。 因此,没有行返回。

需要注意的是,同样是不正确的空集 。 如果上面的子查询将返回没有行 ,则NOT IN的表达将评估为TRUE ,只要左边是NOT NULL

基本上,避免NOT IN (<subquery>)其中可以。 NOT EXISTS几乎总是更胜一筹。
如果你使用它,知道如何使用了NULL值。 更多细节:

  • 找到在哪里参加不存在的记录
  • 它不存在于其他表中选择行


Answer 2:

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';

会给你的公司IDS与指定的日期之后添加的项目的所有公司(没有一家公司将与日之前加入项目的任何公司被退回。)



文章来源: sql query to extract new records