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 小时内选择重复项的主要内容,如果未能解决你的问题,请参考以下文章