使用 DateDiff 的 C# SQL 分组间隔?

发布于 2024-12-17 19:13:10 字数 1695 浏览 4 评论 0原文

我有下表:

RowA     RowB    date_time            RowD  
-------  ------- -------------------  -------
ValueA1  ValueB1 01.01.2001 16:23:01  ValueD1  
ValueA2  ValueB2 01.01.2001 16:23:06  ValueD2  
ValueA3  ValueB3 01.01.2001 16:23:11  ValueD3  
ValueA4  ValueB4 03.01.2001 12:23:01  ValueD4  
ValueA5  ValueB5 03.01.2001 16:23:06  ValueD5  
ValueA6  ValueB6 03.01.2001 16:23:11  ValueD6  
ValueA7  ValueB7 03.01.2001 16:23:16  ValueD7  

该表大约有 50k 行。我想将 5 秒间隔内获取的值分组为 attempts1、尝试 2... 等。我还需要使组 attempts1、尝试 2... 等可访问,以便我可以打开或关闭它们的可见性例如,使用复选框的 DataGridview。

我对 SQL 很陌生,现在我正在寻找解决方案两天,尝试过 GROUP BY、DATEDIFF 和 DATEADD,但大多数我发现的解决方案中的一些只是计算或总结了各组的值。

使用 RowFilter 的解决方案非常棒,但 sql 字符串也将非常受欢迎。

编辑

很抱歉我无法提前回答。你提供的两个结果都不是我想要的,我不确定现在是否可以使用 SQL 来解决我想要的结果。我希望得到的结果表应该如下所示(我添加了一些值,因为我意识到到目前为止我使用的值可能没有明确我想要的内容):

Attempt  RowA    RowB    date_time           RowD  
-------- ------- ------- ------------------- -------
attempt1 ValueA1 ValueB1 01.01.2001 16:23:01 ValueD1   |
attempt1 ValueA2 ValueB2 01.01.2001 16:23:06 ValueD2   | attempt1 since 5s difference (over 3 lines)
attempt1 ValueA3 ValueB3 01.01.2001 16:23:11 ValueD3   |
attempt2 ValueA4 ValueB4 03.01.2001 12:23:01 ValueD4  -> new and one line only attempt (difference bigger than 5s)
attempt3 ValueA5 ValueB5 03.01.2001 16:23:06 ValueD5   |
attempt3 ValueA6 ValueB6 03.01.2001 16:23:11 ValueD6   | attempt3 since 5s difference (over 3 lines)
attempt3 ValueA7 ValueB7 03.01.2001 16:23:16 ValueD7   |
attempt4 ValueA8 ValueB8 04.01.2001 02:16:53 ValueD8   - attempt4 since 5s difference...
attempt4 ValueA9 ValueB9 04.01.2001 02:16:58 ValueD9   - (2 lines)

I have the following table:

RowA     RowB    date_time            RowD  
-------  ------- -------------------  -------
ValueA1  ValueB1 01.01.2001 16:23:01  ValueD1  
ValueA2  ValueB2 01.01.2001 16:23:06  ValueD2  
ValueA3  ValueB3 01.01.2001 16:23:11  ValueD3  
ValueA4  ValueB4 03.01.2001 12:23:01  ValueD4  
ValueA5  ValueB5 03.01.2001 16:23:06  ValueD5  
ValueA6  ValueB6 03.01.2001 16:23:11  ValueD6  
ValueA7  ValueB7 03.01.2001 16:23:16  ValueD7  

The table goes on like that for about 50k lines. I would like to group those values taken in 5s interval as attempt1, attempt 2... etc. I'll also need to make the groups attempt1, attempt2... etc. accessible, so I can turn on or off their visibility in a DataGridview using Checkboxes for example.

I am very new to SQL and I'm looking for a solution for two days now, tried GROUP BY, DATEDIFF and DATEADD, but most of the solutions I found did only count or sum up the values of the groups.

A solution using RowFilter would be awesome but the sql string would be very much appreciated, too.

EDIT

I am sorry I couldn't answer earlier. Both results you offered are not what I was looking for and I am not sure whether the results I wish for can be solved using SQL now. The resulting table I wish for should look like this (I added some Values because I realized that the ones I used until now probably didn't make clear what I wished for):

Attempt  RowA    RowB    date_time           RowD  
-------- ------- ------- ------------------- -------
attempt1 ValueA1 ValueB1 01.01.2001 16:23:01 ValueD1   |
attempt1 ValueA2 ValueB2 01.01.2001 16:23:06 ValueD2   | attempt1 since 5s difference (over 3 lines)
attempt1 ValueA3 ValueB3 01.01.2001 16:23:11 ValueD3   |
attempt2 ValueA4 ValueB4 03.01.2001 12:23:01 ValueD4  -> new and one line only attempt (difference bigger than 5s)
attempt3 ValueA5 ValueB5 03.01.2001 16:23:06 ValueD5   |
attempt3 ValueA6 ValueB6 03.01.2001 16:23:11 ValueD6   | attempt3 since 5s difference (over 3 lines)
attempt3 ValueA7 ValueB7 03.01.2001 16:23:16 ValueD7   |
attempt4 ValueA8 ValueB8 04.01.2001 02:16:53 ValueD8   - attempt4 since 5s difference...
attempt4 ValueA9 ValueB9 04.01.2001 02:16:58 ValueD9   - (2 lines)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

携君以终年 2024-12-24 19:13:10

我不确定仅使用“普通”SQL(没有一些迭代函数,如游标)就可以解决这个问题。

如果您可以确保每次尝试都从整分钟开始并且持续时间少于 60 秒,那么这个简单的方法就可以工作:

  select convert(smalldatetime, date_time), 
         min(RowA), min(RowB), min(RowD), 
         max(RowA), max(RowB), max(RowD)
  from   YourTableName
  group by convert(smalldatetime, date_time)

但这只是因为smalldatetime 消除了 date_time 字段的秒部分。

另外,在我的示例中,我假设 RowA、B 和 D 包含一些渐进的值,我认为这是我的错误假设。

也许您必须在这里编写一些子查询:

更新

此查询应列出所有开始尝试:

 select t1.*
 from   <YourTableName> t1
 where not exists(
     select * 
     from   <YourTableName> t2
     where  t2.date_time >= dateadd(s, -5, t1.date_time) 
     and    t2.date_time < t1.date_time 
 )

示例中数据的结果:

RowA    RowB    date_time               RowD
------- ------- ----------------------- -------   
ValueA1 ValueB1 2001-01-01 16:23:01.000 ValueD1
ValueA4 ValueB4 2001-03-01 12:23:01.000 ValueD4
ValueA5 ValueB5 2001-03-01 16:23:06.000 ValueD5

我不知道您是否需要每次尝试的最后一行也在网格的行中(在同一行中)。这会让事情变得更复杂一些。

更新 2:

如果您使用的是 SQL Server 2005(或更高版本),您可以使用类似于此查询的公共表表达式,该查询为您提供单行中的开始行和结束行:

 with start_rows as (
     select start.* 
     from   <YourTablenName> start
     where  not exists(
       select * 
       from   <YourTableName> start2
       where  start2.date_time >= dateadd(s, -5, start.date_time) 
       and    start2.date_time < start.date_time 
     )
 ),
 stop_rows as (   
     select stop.*
     from   <YourTablenName> stop
     where  not exists(
        select * 
        from <YourTableName> stop2
        where stop2.date_time <= dateadd(s, 5, stop.date_time) 
        and   stop2.date_time > stop.date_time 
     )
 ) 
 select start_rows.*, stop_rows.*
 from   start_rows, stop_rows
 where start_rows.date_time <= stop_rows.date_time
 and    not exists(
    select * from stop_rows sr2
    where sr2.date_time < stop_rows.date_time
    and sr2.date_time >= start_rows.date_time
 )
 order by start_rows.date_time

本例中的结果是:

ValueA1 ValueB1 2001-01-01 16:23:01.000 ValueD1 ValueA3 ValueB3 2001-01-01 16:23:11.000 ValueD3
ValueA4 ValueB4 2001-03-01 12:23:01.000 ValueD4 ValueA4 ValueB4 2001-03-01 12:23:01.000 ValueD4
ValueA5 ValueB5 2001-03-01 16:23:06.000 ValueD5 ValueA7 ValueB7 2001-03-01 16:23:16.000 ValueD7

I'm not sure this can be solved using only "normal" SQL (without some iterative functions like cursors).

If you can assure that every attemps starts at full minutes and lasts less than 60s, then this simple approach could work:

  select convert(smalldatetime, date_time), 
         min(RowA), min(RowB), min(RowD), 
         max(RowA), max(RowB), max(RowD)
  from   YourTableName
  group by convert(smalldatetime, date_time)

But this only works because smalldatetime eliminates the seconds part of your date_time field.

Also, in my example I assume that RowA, B and D contain some values which are progressive, which I think is a wrong assumption of mine.

Probably you'll have to write some subqueries here:

Update

This query should list all starting attempts:

 select t1.*
 from   <YourTableName> t1
 where not exists(
     select * 
     from   <YourTableName> t2
     where  t2.date_time >= dateadd(s, -5, t1.date_time) 
     and    t2.date_time < t1.date_time 
 )

The result for the data in your example:

RowA    RowB    date_time               RowD
------- ------- ----------------------- -------   
ValueA1 ValueB1 2001-01-01 16:23:01.000 ValueD1
ValueA4 ValueB4 2001-03-01 12:23:01.000 ValueD4
ValueA5 ValueB5 2001-03-01 16:23:06.000 ValueD5

I don't know if you need the last row of every attempt in your grid's rows (in the same row) too. That would make things a little more complicated.

Update 2:

If you're using SQL Server 2005 (or newer), you could use Common Table Expressions like this query which gives you start and end row in single rows:

 with start_rows as (
     select start.* 
     from   <YourTablenName> start
     where  not exists(
       select * 
       from   <YourTableName> start2
       where  start2.date_time >= dateadd(s, -5, start.date_time) 
       and    start2.date_time < start.date_time 
     )
 ),
 stop_rows as (   
     select stop.*
     from   <YourTablenName> stop
     where  not exists(
        select * 
        from <YourTableName> stop2
        where stop2.date_time <= dateadd(s, 5, stop.date_time) 
        and   stop2.date_time > stop.date_time 
     )
 ) 
 select start_rows.*, stop_rows.*
 from   start_rows, stop_rows
 where start_rows.date_time <= stop_rows.date_time
 and    not exists(
    select * from stop_rows sr2
    where sr2.date_time < stop_rows.date_time
    and sr2.date_time >= start_rows.date_time
 )
 order by start_rows.date_time

The result in this case is:

ValueA1 ValueB1 2001-01-01 16:23:01.000 ValueD1 ValueA3 ValueB3 2001-01-01 16:23:11.000 ValueD3
ValueA4 ValueB4 2001-03-01 12:23:01.000 ValueD4 ValueA4 ValueB4 2001-03-01 12:23:01.000 ValueD4
ValueA5 ValueB5 2001-03-01 16:23:06.000 ValueD5 ValueA7 ValueB7 2001-03-01 16:23:16.000 ValueD7
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文