SQL查询到Linq Lambda

时间:2019-03-08 02:59:28

标签: sql-server linq

我在SQL Server中有一个具有以下架构的表:

CREATE TABLE [dbo].[MyTable]
(
       [PatientId] [INT] NOT NULL, 
       [Timestamp] [DATETIME] NOT NULL,
       [FiO2] [TINYINT] NULL
)

和以下查询,它们按5分钟的时差分组,并显示每个分组数据的FiO2和时间戳的平均值:

SELECT 
    AVG(FiO2) AS FiO2, 
    CAST(AVG(CAST([TimeStamp] AS FLOAT)) AS DATETIME) TimeStamp
FROM 
    MyTable
WHERE 
    PatientId = 97209520
GROUP BY 
    DATEADD(MINUTE, DATEDIFF(MINUTE,'2019-03-13 12:08:52.447',[TimeStamp]) / 5 * 5, 0)

以下是示例数据:

enter image description here

这是我的SQL查询的结果:

enter image description here

我已经使用过此linQ查询

var averagedData = loadedData.GroupBy(t => new {
                    t.PatientId, 
                    TimeBracket = new DateTime(t.TimeStamp.Year, t.TimeStamp.Month, t.TimeStamp.Day, t.TimeStamp.Hour, t.TimeStamp.Minute,0).AddMinutes(5 - t.TimeStamp.Minute % 5)
                })
                .Select(p => new MonitorData{
                    PatientId = p.Key.PatientId,
                    FiO2 = (byte) p.Average(q => q.FiO2),
                    TimeStamp = new DateTime((long) p.Average(t => t.TimeStamp.Ticks), p.Key.TimeBracket.Kind)
                })
                .ToList();

由于某种原因,它返回5条记录,而不是4条具有不同计算值的记录。出于某种原因,它会将前两行分为一组,其余的分为四组,然后计算平均值。

1 个答案:

答案 0 :(得分:0)

我无法找出如何作为完全本地的LINQ to SQL查询来执行此操作,但是如果进行分组,然后使用.AsEnumerable()将结果拖入内存,则可以创建平均值...

第二次修改

这是LINQ,用于匹配问题中提供的查询的输出。它将每条记录四舍五入到最接近的5分钟,并保留秒和毫秒的数据。

  var averagedData = loadedData
    .GroupBy(t => new
    {
      t.PatientId,
      TimeBracket = new DateTime(t.TimeStamp.Year, t.TimeStamp.Month, t.TimeStamp.Day, t.TimeStamp.Hour, (int)Math.Round(t.TimeStamp.Minute / 5.0) * 5, t.TimeStamp.Second, t.TimeStamp.Millisecond)
    })
    .Select(g => new MonitorData
    {
      PatientId = g.Key.PatientId,
      FiO2 = (byte) g.Average(p => p.FiO2),
      TimeStamp = new DateTime((long) g.Average(t => t.TimeStamp.Ticks), g.Key.TimeBracket.Kind)
    }).ToList();

=================================

修改

此版本应与NHibernate一起使用,但这意味着将所有适当的患者行加载到内存中,然后进行计算:

var averaged =
  table.Where(x => x.PatientId == 2)
       .AsEnumerable()
       .GroupBy(t => new
       {
         t.PatientId,
         TimeBracket =
         new DateTime(t.TimeStamp.Year, t.TimeStamp.Month, t.TimeStamp.Day, t.TimeStamp.Hour, t.TimeStamp.Minute,
           0).AddMinutes(5 - t.TimeStamp.Minute % 5)
       })
       .Select(g => new MyTable
       {
         PatientId = g.Key.PatientId,
         FiO2 = (byte) g.Average(p => p.FiO2),
         TimeStamp = new DateTime((long) g.Average(t => t.TimeStamp.Ticks), g.Key.TimeBracket.Kind)
       }).ToList();

=================================

这假设您在项目中拥有EntityFramework,并有权访问DbFunctions

var averaged = 
    table.Where(x => x.PatientId == 97209520)
    .GroupBy(t => new {
        t.PatientId,
        t.TimeStamp,
        TimeBracket = DbFunctions.AddMinutes(DbFunctions.CreateDateTime(t.TimeStamp.Year, t.TimeStamp.Month, t.TimeStamp.Day, t.TimeStamp.Hour, t.TimeStamp.Minute, 0), 5 - t.TimeStamp.Minute % 5).Value
    })
    .AsEnumerable()
    .Select(g => new MyTable
    {
        PatientId = g.Key.PatientId,
        FiO2 = (byte) g.Average(p => p.FiO2),
        TimeStamp = new DateTime((long) g.Average(t => t.TimeStamp.Ticks), g.Key.TimeBracket.Kind)
    }).ToList();