【问题标题】:Select Distinct Rows Outside of Time Frame选择时间范围之外的不同行
【发布时间】:2012-01-16 05:24:26
【问题描述】:

我正在尝试使用 SQL 根据一个条目与下一个条目之间的时间差来选择不同的数据条目。用一个例子更容易解释:

我的数据表有

Part    DateTime   
123     12:00:00
123     12:00:05
123     12:00:06
456     12:10:23
789     12:12:13
123     12:14:32

我想返回所有行,但如果有多个条目具有相同的“零件”编号,我只想检索那些至少相差 5 分钟的条目。

查询应该返回:

Part    DateTime   
123     12:00:00
456     12:10:23
789     12:12:13
123     12:14:32

我使用的代码如下:

SELECT data1.*, to_char(data1.scan_time, 'yyyymmdd hh24:mi:ss') 

FROM data data1 

where exists
(
    select * 

    from data data2

    where data1.part_serial_number = data2.part_serial_number AND 
    data2.scan_time + 5/1440 >= data1.scan_time 
    and data2.info is null
)

order by to_char(data1.scan_time, 'yyyymmdd hh24:mi:ss'), data1.part_serial_number

不幸的是,这不起作用。有谁知道我做错了什么或可以提出替代方法?

谢谢

【问题讨论】:

  • 我想知道您是否尝试过我的方法。是不是太简单了?

标签: sql oracle distinct


【解决方案1】:

这还没有得到验证,但本质上,诀窍是按部分分组和时间除以 5 分钟(下限)。

select part, min(scan_time)
from data
group by part, floor(scan_time/(5/1440))
order by scan_time;

【讨论】:

    【解决方案2】:

    AFJ,

    假设我们有一个新字段,告诉我们在前 5 分钟内是否存在该部分的先前条目,然后,将该字段设置为 False 的行得到结果。

    select  
      Part, 
      DateTime,
      coalesce(
        (select distinct 1
         from data ds
         where ds.Part = d.Part
           and ds.DateTime between d.DateTime and d.DateTime - 5/1440
        )
        , 0) as exists_previous 
    from data d
    

    子查询检查它们是否是前 5 分钟间隔内具有相同 Part 的行

    结果必须是:

    Part    DateTime   exists_previous
    123     12:00:00   0
    123     12:00:05   1
    123     12:00:06   1
    456     12:10:23   0
    789     12:12:13   0
    123     12:14:32   0
    

    现在,过滤以仅获取具有 0 的行:

       select Part, DateTime from 
       (select  
          Part, 
          DateTime,
          coalesce(
            (select distinct 1
             from data ds
             where ds.Part = d.Part
               and ds.DateTime between d.DateTime and d.DateTime - 5/1440
            )
            , 0) as exists_previous 
        from data D
       ) T where T.exists_previous = 0
    

    免责声明:未经测试。

    【讨论】:

    • 感谢 danihp。我了解您的查询是如何工作的,但是我无法让子查询正常工作。它返回exists_previous列中所有带有“0”的行。
    【解决方案3】:

    分析函数来拯救。

    您可以使用解析函数LEAD获取零件下一行的数据。

    SQL> ed
    Wrote file afiedt.buf
    
      1  with x as (
      2    select 123 part, timestamp '2011-12-08 00:00:00' ts
      3      from dual
      4    union all
      5    select 123, timestamp '2011-12-08 00:00:05'
      6      from dual
      7    union all
      8    select 123, timestamp '2011-12-08 00:00:06'
      9      from dual
     10    union all
     11    select 456, timestamp '2011-12-08 00:10:23'
     12      from dual
     13    union all
     14    select 789, timestamp '2011-12-08 00:12:13'
     15      from dual
     16    union all
     17    select 123, timestamp '2011-12-08 00:14:32'
     18      from dual
     19  )
     20  select part,
     21         ts,
     22         lead(ts) over (partition by part order by ts) next_ts
     23*   from x
    SQL> /
    
          PART TS                              NEXT_TS
    ---------- ------------------------------- -------------------------------
           123 08-DEC-11 12.00.00.000000000 AM 08-DEC-11 12.00.05.000000000 AM
           123 08-DEC-11 12.00.05.000000000 AM 08-DEC-11 12.00.06.000000000 AM
           123 08-DEC-11 12.00.06.000000000 AM 08-DEC-11 12.14.32.000000000 AM
           123 08-DEC-11 12.14.32.000000000 AM
           456 08-DEC-11 12.10.23.000000000 AM
           789 08-DEC-11 12.12.13.000000000 AM
    
    6 rows selected.
    

    完成此操作后,您可以创建一个内联视图,只需选择下一个日期在当前日期后 5 分钟以上的那些行。

    SQL> ed
    Wrote file afiedt.buf
    
      1  with x as (
      2    select 123 part, timestamp '2011-12-08 00:00:00' ts
      3      from dual
      4    union all
      5    select 123, timestamp '2011-12-08 00:00:05'
      6      from dual
      7    union all
      8    select 123, timestamp '2011-12-08 00:00:06'
      9      from dual
     10    union all
     11    select 456, timestamp '2011-12-08 00:10:23'
     12      from dual
     13    union all
     14    select 789, timestamp '2011-12-08 00:12:13'
     15      from dual
     16    union all
     17    select 123, timestamp '2011-12-08 00:14:32'
     18      from dual
     19  )
     20  select part,
     21         ts
     22    from (
     23      select part,
     24             ts,
     25             lead(ts) over (partition by part order by ts) next_ts
     26        from x )
     27   where next_ts is null
     28*     or next_ts > ts + interval '5' minute
    SQL> /
    
          PART TS
    ---------- -------------------------------
           123 08-DEC-11 12.00.06.000000000 AM
           123 08-DEC-11 12.14.32.000000000 AM
           456 08-DEC-11 12.10.23.000000000 AM
           789 08-DEC-11 12.12.13.000000000 AM
    

    【讨论】:

      猜你喜欢
      • 2019-07-14
      • 1970-01-01
      • 2018-08-14
      • 2013-04-09
      • 1970-01-01
      • 1970-01-01
      • 2013-03-27
      • 1970-01-01
      相关资源
      最近更新 更多