sql 查询 - 在 12 小时内选择重复项

Posted

技术标签:

【中文标题】sql 查询 - 在 12 小时内选择重复项【英文标题】:sql query - select duplicates within a 12 hour period 【发布时间】:2009-01-08 15:10:03 【问题描述】:

如果我有如下数据

一个 | 01/01/2008 00:00:00

B | 01/01/2008 01:00:00

一个 | 01/01/2008 11:59:00

C | 02/01/2008 00:00:00

D | 02/01/2008 01:00:00

D | 02/01/2008 20:00:00

我只想选择其标识符(A、B、C 或 D)在 12 小时内出现两次的记录。在上面的这个例子中,这只是'A'

谁能帮忙(这是一个Oracle数据库)

谢谢

M

【问题讨论】:

当你说“这只会是A”时,你的意思不是“A和D”吗? 否:20:00:00 是 01:00:00 之后的 12 小时以上。 另外,当您说“12 小时周期”时,是指时钟定义的 12 小时周期,还是从第一次出现开始的 12 小时周期?即 01/01/2008 23:00 和 02/01/2008 01:00 算吗? @Joel:哎呀!抱歉——出于某种原因,我读了 12 个小时,想了 24 个小时…… 【参考方案1】:
 Select Distinct A.Identifer  
  From Table A
    Join Table B --  EDIT to eliminate self Joins (to same row)
        On A.PrimKey <> B.PrimaryKey
           And A.Identifer = B.Identifer               
           -- EDIT to fix case where 2 at same time
           And A.OccurTime >=  B.OccurTime 
           And A.OccurTime < B.OccurTime + .5

并实施评论中提出的问题, (忽略不同日期的记录)

-- 对于 SQL Server,

   Select Distinct A.Identifer  
    From Table A
      Join Table B 
        On A.PrimKey <> B.PrimaryKey
           And A.Identifer = B.Identifer
           -- EDIT to fix case where 2 at same time
           And A.OccurTime >= B.OccurTime  
           And A.OccurTime < B.OccurTime + .5
    Where DateDiff(day, A.OccurTime, B.OccurTime) = 0

-- 或者对于 oracle...

 Select Distinct A.Identifer  
    From Table A
      Join Table B 
        On A.PrimKey <> B.PrimaryKey
           And A.Identifer = B.Identifer
           -- EDIT to fix case where 2 at same time
           And A.OccurTime >= B.OccurTime  
           And A.OccurTime < B.OccurTime + .5
 Where Trunc(A.OccurTime) = Trunc(B.OccurTime)

【讨论】:

为避免每个重复集返回两次,添加:AND A.OccurTime > B.OccurTime 这也可以让你做一个简单的 > 而不是 BETWEEN 我只是将其更改为 0 到 .5 之间 - 应该这样做 看来您的查询当前将返回每一行,因为 A & B 中的同一行将具有相同的标识符,而 OccurTime 的差异将始终为 0。所以您可能想抛出一个a.ROWID != b.ROWID 在那里。 如果标识符和发生时间的组合是唯一的,乔尔建议的 A.OccurTime > B.OccurTime 也可以【参考方案2】:
Select    
  A.Id
From    
  YourTable A 
Where    
  A.YourDateTime Between :StartDateTime and :EndDateTime 
Group By    
  A.Id
Having    
  COUNT(A.Id) = 2

【讨论】:

"Having Count(A.Id) > 1" 如果可能超过 2 个 他的意思是说在任何 12 小时内......不是一个特定的时间范围【参考方案3】:

我没有检查威廉的查询,但我会认真考虑使用他所拥有的一切。分析是炸弹。每当您发现自己将表连接回自身时,几乎都可以保证有机会使用分析,并且每次都会使用一个表引用两次来执行查询。

您会惊讶分析解决方案的速度有多快。

【讨论】:

【参考方案4】:
SELECT identifier
  FROM table_name outer
 WHERE EXISTS( SELECT 1
                 FROM table_name inner
                WHERE inner.identifier  = outer.identifier
                  AND inner.date_column BETWEEN outer.date_column AND outer.date_column + interval '12' hour
                  AND inner.rowid != outer.rowid )

【讨论】:

【参考方案5】:

我不能 100% 确定您的要求,但是这可能会给您一些关于如何做您需要的想法的想法。例如,您说的正好是 2;如果有 3 次出现怎么办?等等

create table t (ident varchar2(16), occurance timestamp);

insert into t (ident, occurance) values ('a', to_date('20080101000000', 'yyyymmddhh24miss'));

insert into t (ident, occurance) values ('b', to_date('20080101010000', 'yyyymmddhh24miss'));

insert into t (ident, occurance) values ('a', to_date('20080101115900', 'yyyymmddhh24miss'));

insert into t (ident, occurance) values ('c', to_date('20080102000000', 'yyyymmddhh24miss'));

insert into t (ident, occurance) values ('d', to_date('20080102010000', 'yyyymmddhh24miss'));

insert into t (ident, occurance) values ('d', to_date('20080102200000', 'yyyymmddhh24miss'));

insert into t (ident, occurance) values ('d', to_date('20080103020000', 'yyyymmddhh24miss'));

select ident, occurance
from
(
select ident, occurance,
    lag(occurance) over (partition by ident order by occurance) previous, 
    lead(occurance) over (partition by ident order by occurance) next 
from t
)
where 
    ((occurance-previous<interval'12:00' hour to minute and extract(day from occurance) = extract(day from previous))
    or (next-occurance<interval'12:00' hour to minute and extract(day from occurance) = extract(day from next)))
/

【讨论】:

【参考方案6】:
SELECT namecol FROM tbl A
WHERE EXISTS (
  SELECT 1 from tbl B
  WHERE b.namecol = a.namecol
  AND b.timestamp > a.timestamp
  AND b.timestamp - 0.5 <= a.timestamp )

【讨论】:

巧妙地包含 b.timestamp > a.timestamp 谓词以启用索引。不过,你应该写个便条

以上是关于sql 查询 - 在 12 小时内选择重复项的主要内容,如果未能解决你的问题,请参考以下文章

SQL 查询有效地选择不完美的重复项

SQL 查询以查找由字母分隔的重复项

查询删除重复项

如何删除唯一行并保持重复? SQL

从 SQLite 中的 SQL 查询结果中删除重复项

SQL - 选择最大具有不同值的重复项