【问题标题】:Return a set of records only if they are in certain order仅当它们按特定顺序返回一组记录
【发布时间】:2016-10-20 17:45:38
【问题描述】:

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

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
.    .              .

我想编写一个查询,该查询将返回给我一组记录,前提是这些记录按特定的顺序排列。

例如,对于上面的数据,我想要一个查询: "获取 Action#2 发生在 Action#1 之后的时间,按时间戳顺序按顺序。"

应该返回给我:

##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 风格的答案

【问题讨论】:

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


【解决方案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 个连续记录的其他测试。

【讨论】:

  • 我认为在c#端做事是个好主意。它简化了问题。请注意,这两个动作不一定相等。在我的情况下,我将不得不稍微修改此代码以首先按顺序从 DB 中获取条目,然后将序列中的每个元素与预期的有序序列进行比较。感谢您的建议。
【解决方案2】:

你可以在Sql server端做,这样可以减少结果集的大小。

TimeStamp 排序时,首先找到常量Action 的岛,它们只过滤长度= 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

【讨论】:

    【解决方案3】:

    我没有检查它(所以我很高兴知道它是否对你有用;我正在用 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); 
    

    【讨论】:

    • sgivmal,谢谢,但这不起作用有两个原因。时间戳不一定相差1。ID也不一定相差1。此外,这两个动作不一定相等。顺序模式可以是:Action#1 然后 Action#3
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-16
    • 2017-04-13
    • 1970-01-01
    • 2020-05-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多