仅当它们按特定顺序返回时才返回一组记录

时间:2016-06-19 10:12:12

标签: c# sql database linq linq-to-sql

我有一张表,其中包含按时间戳排序的以下记录

Id   TimeStamp      Action
--   ---------      ------
1    #1             ActionType#1
2    #2             ActionType#2
3    #3             ActionType#2
4    #4             ActionType#1
5    #5             ActionType#3
.    .              .
.    .              .
.    .              .
52   #52             ActionType#1
53   #53             ActionType#2
.    .              .

我想编写一个查询,只有当记录按特定的顺序排列时才会返回给我一组记录。

例如,在上面的数据中,我想要一个查询: “根据时间戳顺序,按行动#1顺序执行动作#2时获取。”

应该回到我身边:

##First matching sequence

2    #2             ActionType#1 
3    #3             ActionType#2 
##Second matching sequence

52   #2             ActionType#1 
53   #3             ActionType#2

注意:这是在ASP.NET应用程序中,因此欢迎使用LINQ样式的答案

3 个答案:

答案 0 :(得分:1)

我会考虑一个基于for循环表的有效解决方案:

List<myRecordClass> myResults = new List<myRecordClass>();

for (int i = 1; i < myTable.Count; i++)
    {
        if (myTable.ElementAt(i).Action == myTable.ElementAt(i-1).Action)
        {
            myResults.Add(myTable.ElementAt(i - 1));
            myResults.Add(myTable.ElementAt(i));
        }
    }

这将允许您实现涉及例如3个连续记录的其他测试。

答案 1 :(得分:0)

您可以在Sql server端执行此操作,并以这种方式减小结果集的大小。

首先按Action排序,找到常数为TimeStamp的岛屿,并且只过滤长度为2的岛屿

select Id,TimeStamp, Action
from (
    select *, cnt = count(*) over(partition by grp)
    from (
        select *, grp = row_number() over(order by TimeStamp) - row_number() over(partition by Action order by TimeStamp) 
        from (values
                (1 ,'#1' ,'ActionType#1'),
                (2 ,'#2' ,'ActionType#2'),
                (3 ,'#3' ,'ActionType#2'),
                (4 ,'#4' ,'ActionType#1'),
                (5 ,'#5' ,'ActionType#3'),
                (51,'#51','ActionType#2'),
                (52,'#52','ActionType#2'),
                (53,'#53','ActionType#2')
        ) t (Id,TimeStamp,Action)  
     ) t1
   ) t2
where cnt=2
order by TimeStamp

答案 2 :(得分:-1)

我没有检查它(所以我很乐意知道它是否适用于你;我正在用mySQL编写):

SELECT a.Id, a.Id+1, a.Action 
   FROM #yourTable a
     INNER JOIN #yourTable (same one as above) b
       ON (a.Id=b.Id-1) AND (a.Action=b.Action);