【问题标题】:Select rows from table where value in column appears ones从表中选择列中出现值的行
【发布时间】:2015-07-29 16:04:14
【问题描述】:

我有下表,其中三个字段如下所示:

表:Testing

create table testing
(
   colnum varchar(10),
   coldate date,
   colid int
);

插入:

insert into testing values('111','2015-01-01',1);
insert into testing values('111','2015-01-02',1);
insert into testing values('111','2015-01-03',1);
insert into testing values('111','2015-01-04',1);
insert into testing values('111','2015-01-05',1);
insert into testing values('222','2015-01-01',1);
insert into testing values('333','2015-01-01',1);

索引创建:

create clustered index id_idx on testing(colid);
create nonclustered index date_nidx on testing(coldate);
create nonclustered index num_nidx on testing(colnum);

注意:现在我想显示仅在特定日期和特定 ID 而不是其他日期的记录。

例如:我想显示ONLY IN指定日期和ID但不显示其他日期的记录。

给定日期:2015-01-01
给定 ID:1

为此我写了以下查询:

select * from testing
where coldate in ('2015-01-01')
      and coldid = 1
      and colnum not in(select colnum from testing where coldid = 1 and
                        coldate in('2015-01-02','2015-01-03','2015-01-04'
                             '2015-01-05');

结果:

colnum   coldate     colid
--------------------------
222     2015-01-01    1
333     2015-01-01    1

说明:查询显示两条记录,因为两条记录都只有特定日期和 id 记录 111 未显示,因为它也属于其他日期您可以在上表中看到。

上述查询对我来说很好但是需要更多时间来执行数十亿条记录。

【问题讨论】:

  • 根据你的情况,111也应该返回?
  • 你的表有索引吗?
  • 请张贴创建索引脚本。
  • 试试这个:create nonclustered index nci_testing on testing (colid, coldate) include(colnum)
  • 是的,这将对INSERTDELETE 产生影响。但是您现在可以删除您创建的其他索引。

标签: sql sql-server sql-server-2008 sql-server-2008-r2


【解决方案1】:

试试这个查询:

SELECT colnum, coldate,colid 
FROM 
( 
 select *,COUNT(1) OVER (PARTITION BY colnum) as cnt 
from (SELECT DISTINCT colnum, coldate,colid from testing ) t
) q
where  q.cnt=1 and q.coldate in ('2015-01-01') and q.colid = 1

小提琴链接:http://sqlfiddle.com/#!6/650c0/4

【讨论】:

  • 这与预期结果不匹配,因为 '111','2015-01-01',1 将在输出中
  • 不要认为这会解决问题。
  • 是的,这是有道理的,这是据我所知最快的方法。
  • @DhruvJoshi,只需插入此insert into testing values('333','2015-01-01',1); 3 次并运行您的脚本。它必须显示在结果中,因为它仅在同一日期但多次但必须显示在结果中。
  • @DhruvJoshi,结果仍然有错误。如果我插入这个insert into testing values('333','2015-01-08',8);,那么333 不应该出现在结果中。请检查一下。
【解决方案2】:

我根据你例子中的结果做了一些假设。

  • 您需要特定日期而不是其他日期
  • 你想要所有的 colid(s)(根据你的例子)

你能检查一下这是否是预期的结果吗?

SELECT t.* 
FROM   testing t 
       LEFT JOIN (SELECT * 
                  FROM   testing 
                  WHERE  coldate <> '2015-01-01') x 
              ON x.colnum = t.colnum 
WHERE  x.colnum IS NULL 

【讨论】:

    【解决方案3】:

    试试下面这个。你也会得到记录 111。

    从测试中选择 *

    coldate = '2015-01-01'

    和colid = 1;

    对于执行时间,您只需在该表上创建一个索引。这样会提高您的执行性能。

    谢谢。

    【讨论】:

      【解决方案4】:

      将速度与此进行比较会很有趣:

      SELECT colnum,colid, min(coldate) as coldate
      FROM testing 
      GROUP BY colnum,colid
      HAVING COUNT(DISTINCT coldate) = 1 
        AND colid = 1
        AND min(coldate) = '2015-01-01'
      

      【讨论】:

      • 只需插入此insert into testing values('333','2015-01-01',1); 3 次并运行您的脚本。它必须显示在结果中,因为它仅在同一日期但多次但必须显示在结果中
      • 我已更新查询以计算不同的日期数
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-10
      • 1970-01-01
      • 2016-11-02
      • 1970-01-01
      相关资源
      最近更新 更多