C# 使用linq2sql提前查询有间隙的数据

C# 使用linq2sql提前查询有间隙的数据,c#,linq-to-sql,C#,Linq To Sql,Hi i have table:带有ValueId、Timestamp、Value和BelongTo的值。每15分钟就有一个新行插入到该表中,带有新值、当前时间戳和特定的BelongTo字段。现在我想找出间隔,我是指一个接一个的时间戳超过15分钟的值 我试着这样做: var gaps = from p1 in db.T_Values join p2 in db.T_Values on p1.TimeStamp.AddMinutes(15) equal

Hi i have table:带有ValueId、Timestamp、Value和BelongTo的值。每15分钟就有一个新行插入到该表中,带有新值、当前时间戳和特定的BelongTo字段。现在我想找出间隔,我是指一个接一个的时间戳超过15分钟的值

我试着这样做:

var gaps = from p1 in db.T_Values
                       join p2 in db.T_Values on p1.TimeStamp.AddMinutes(15) equals p2.TimeStamp
                       into grups where !grups.Any() select new {p1};
这是可行的,但我不知道这是否是最优的,你觉得呢?我不知道怎么加上p1.BelongTo==1。因为此查询查找所有数据

乔恩告诉我

var gaps = from p1 in db.T_Values
           where p1.BelongTo == 1
           where !db.T_Values.Any(p2 => p1.TimeStamp.AddMinutes(15) == p2.Timestamp)
           select p1;
Jon最后一个查询被转换为:

exec sp_executesql N'SELECT [t0].[ValueID], [t0].[TimeStamp], [t0].[Value],
                    [t0].[BelongTo], [t0].[Type]
FROM [dbo].[T_Values] AS [t0]
WHERE (NOT (EXISTS(
SELECT NULL AS [EMPTY]
FROM [dbo].[T_Values] AS [t1]
WHERE DATEADD(ms, (CONVERT(BigInt,@p0 * 60000)) % 86400000,
DATEADD(day, (CONVERT(BigInt,@p0 * 60000)) / 86400000, [t0].[TimeStamp])) = [t1].[TimeStamp]
))) AND ([t0].[BelongTo] = @p1)',N'@p0 float,@p1 int',@p0=15,@p1=1
除非所有行都有相同的belongTo,否则它是有效的,当有行的belongTo有许多不同的值时,我注意到我需要添加到sql:and[t1].belongTo=1,最后应该是这样的

N'SELECT [t0].[ValueID], [t0].[TimeStamp], [t0].[Value], [t0].[BelongTo], [t0].[Type]
FROM [dbo].[T_Values] AS [t0]
   WHERE (NOT (EXISTS(
SELECT NULL AS [EMPTY]
FROM [dbo].[T_Values] AS [t1]
WHERE DATEADD(ms, (CONVERT(BigInt,@p0 * 60000)) % 86400000, 
DATEADD(day, (CONVERT(BigInt,@p0 * 60000)) / 86400000, [t0].[TimeStamp])) = [t1].[TimeStamp]
and [t1].BelongTo = 1  
  ))) AND ([t0].[BelongTo] = @p1)',N'@p0 float,@p1 int',@p0=15,@p1=1
换句话说:

SELECT  TimeStamp
FROM [dbo].[T_Values] AS [t0]
WHERE NOT( (EXISTS (SELECT NULL AS [EMPTY]
FROM [dbo].[T_Values] AS [t1]
WHERE DATEADD(MINUTE, 15, [t0].[TimeStamp]) = [t1].[TimeStamp])))
AND ([t0].[BelongTo] = 1)
应该换成

SELECT  TimeStamp
FROM [dbo].[T_Values] AS [t0]
WHERE NOT( (EXISTS (SELECT NULL AS [EMPTY]
FROM [dbo].[T_Values] AS [t1]
WHERE DATEADD(MINUTE, 15, [t0].[TimeStamp]) = [t1].[TimeStamp] and [t1].BelongTo=1)))
AND ([t0].[BelongTo] = 1)
但我仍在思考如何将此添加到linkq中

var gaps = dbT_Values.Take(dbT_Values.Count()-1)
                     .Select((p, index) => new {P1 = p, P2 = dbT_Values.ElementAt(index + 1)})
                     .Where(p => p.P1.BelongsTo == 1 && p.P1.TimeStamp.AddMinutes(15).Equals(p.P2.TimeStamp)).Select(p => p.P1);

添加额外的
where
子句很容易(同时我将删除无意义的匿名类型):

我不知道你为什么要分组。。。我本以为这会更简单:

var gaps = from p1 in db.T_Values
           where p1.BelongTo == 1
           where !db.T_Values.Any(p2 => p1.TimeStamp.AddMinutes(15) == p2.Timestamp)
           select p1;
至于性能,请查看生成的SQL以及它在SQL profiler中的外观

编辑:如果您需要
目录
检查两个版本(有意义),我建议:

var sequence = db.T_Values.Where(p => p.BelongTo == 1);

var gaps = from p1 in sequence
           where !sequence.Any(p2 => p1.TimeStamp.AddMinutes(15) == p2.Timestamp)
           select p1;

我让乔恩·斯基特来回答,因为那是你的希望;mon,我正在寻找所有人的帮助,如果有人能说关于这个查询有多优化的话,这个查询将是greatin查询,就像你说的var gaps=from p1 in db.T_value,其中p1.BelongTo==1 where!db.T_Values.Any(p2=>p1.TimeStamp.AddMinutes(15)==p2.TimeStamp)选择p1;我们不能把两个时间放在哪里,nad p2不可用,我也想知道why@kosnkov字体恐怕我不明白你的评论
p2
仅在
任何调用中可用,因为它是lambda表达式中的参数。@Jon很抱歉,Jon,你完全正确,我今天将调查生成sql过程的这两个查询之间的性能,我将告诉你它是如何转换的,最快的方法是什么。非常感谢。我检查了,这两个查询都被转换为同一个存储过程:exec sp_executesql N'SELECT[t0].[ValueID],[t0].[timestack],[t0].[BelongTo],[t0].[Type]FROM[dbo].[T_Values]AS[t0]WHERE(不存在)(选择NULL作为[dbo]的[EMPTY]。[T_Values]作为[t1]其中DATEADD(ms),[CONVERT(BigInt,@p0*60000))%86400000,DATEADD(day,(CONVERT(BigInt,@p0*60000))/86400000,[t0].[TimeStamp])=[t1].[TimeStamp]))和([t0].[BelongTo]=@p1),N'@p0 float,@p1 int',@p0=15,@p1=19241,这真是太快了,老实说,它不起作用,因为在将一个表连接到另一个表时,join没有考虑到属于。我很抱歉,但在您的查询中,我遇到了以下错误:查询运算符“Select”使用了不受支持的重载。我将它稍微改为:var gaps1=db.t_Values.take(db.T_Values.Count()-1)。选择((p,index)=>new{P1=p,P2=db.T_Values.ElementAt(index+1))。其中(p=>p.P1.InputID==1&&p.P1.TimeStamp.AddMinutes(15)。等于(p.P2.TimeStamp))。选择(p=>p.P1);这是我正在使用的重载。您确实有
使用System.Linq;
,不是吗?是的,我正在使用.System.Linq,并且此查询确实给我错误,查询运算符“Select”使用了不受支持的重载。如果可以,请自行尝试。
var sequence = db.T_Values.Where(p => p.BelongTo == 1);

var gaps = from p1 in sequence
           where !sequence.Any(p2 => p1.TimeStamp.AddMinutes(15) == p2.Timestamp)
           select p1;