转换包含row_number分区,sum partitioning和having子句的复杂T-SQL查询

时间:2016-08-30 16:43:56

标签: c# linq linq-to-sql linq-to-entities linq-to-xml

我不得不采取不同的方法,这是我在本网站上发布的前一个例子中所做的转换。

以下是我正在使用的简单数据集,以便尝试在我的C#应用​​程序中将我的T-SQL转换为Linq:

create table #sampledata 
(
    name nvarchar(50),
    sampletime datetime,
    samplevalue decimal, 
);

insert into #sampledata (name, sampletime, samplevalue) values
('ABC1235', cast('2016/01/01 10:00:00 AM' as datetime), 50.00),
('ABC1235', cast('2016/01/01 10:05:00 AM' as datetime), 50.00),
('ABC1235', cast('2016/01/01 10:10:00 AM' as datetime), 50.00),
('ABC1235', cast('2016/01/01 10:15:00 AM' as datetime), null),
('ABC1235', cast('2016/01/01 10:20:00 AM' as datetime), null),
('ABC1235', cast('2016/01/01 10:25:00 AM' as datetime), null),
('ABC1235', cast('2016/01/01 10:30:00 AM' as datetime), 50.00),
('ABC1235', cast('2016/01/01 10:35:00 AM' as datetime), 50.00),
('ABC1235', cast('2016/01/01 10:40:00 AM' as datetime), 50.00),
('ABC1235', cast('2016/01/01 10:45:00 AM' as datetime), 50.00),
('ABC1235', cast('2016/01/01 10:50:00 AM' as datetime), 50.00),
('ABC1235', cast('2016/01/01 10:55:00 AM' as datetime), 50.00),
('ABC1235', cast('2016/01/01 11:00:00 AM' as datetime), 50.00),
('ABC1235', cast('2016/01/01 11:05:00 AM' as datetime), null),
('ABC1235', cast('2016/01/01 11:10:00 AM' as datetime), null),
('ABC1235', cast('2016/01/01 11:15:00 AM' as datetime), 50.00),
('ABC1235', cast('2016/01/01 11:20:00 AM' as datetime), 50.00),
('ABC1235', cast('2016/01/01 11:25:00 AM' as datetime), 50.00),
('ABC1235', cast('2016/01/01 11:30:00 AM' as datetime), null),
('ABC1235', cast('2016/01/01 11:35:00 AM' as datetime), 50.00),
('ABC1235', cast('2016/01/01 11:40:00 AM' as datetime), 50.00),
('ABC1235', cast('2016/01/01 11:45:00 AM' as datetime), 50.00),
('ABC1235', cast('2016/01/01 11:50:00 AM' as datetime), null),
('ABC1235', cast('2016/01/01 11:55:00 AM' as datetime), null),
('ABC1235', cast('2016/01/01 12:00:00 PM' as datetime), 50.00),
('ABC1235', cast('2016/01/01 12:05:00 PM' as datetime), null),
('ABC1235', cast('2016/01/01 12:10:00 PM' as datetime), null),
('ABC1235', cast('2016/01/01 12:15:00 PM' as datetime), null),
('ABC1235', cast('2016/01/01 12:20:00 PM' as datetime), null),
('ABC1235', cast('2016/01/01 12:25:00 PM' as datetime), null),
('ABC1235', cast('2016/01/01 12:30:00 PM' as datetime), null),
('ZYA4567', cast('2016/01/01 10:00:00 AM' as datetime), 50.00),
('ZYA4567', cast('2016/01/01 10:05:00 AM' as datetime), 50.00),
('ZYA4567', cast('2016/01/01 10:10:00 AM' as datetime), 50.00),
('ZYA4567', cast('2016/01/01 10:15:00 AM' as datetime), null),
('ZYA4567', cast('2016/01/01 10:20:00 AM' as datetime), null),
('ZYA4567', cast('2016/01/01 10:25:00 AM' as datetime), null),
('ZYA4567', cast('2016/01/01 10:30:00 AM' as datetime), null),
('ZYA4567', cast('2016/01/01 10:35:00 AM' as datetime), 50.00),
('ZYA4567', cast('2016/01/01 10:40:00 AM' as datetime), 50.00),
('ZYA4567', cast('2016/01/01 10:45:00 AM' as datetime), 50.00),
('ZYA4567', cast('2016/01/01 10:50:00 AM' as datetime), 50.00),
('ZYA4567', cast('2016/01/01 10:55:00 AM' as datetime), 50.00),
('ZYA4567', cast('2016/01/01 11:00:00 AM' as datetime), 50.00),
('ZYA4567', cast('2016/01/01 11:05:00 AM' as datetime), null),
('ZYA4567', cast('2016/01/01 11:10:00 AM' as datetime), null),
('ZYA4567', cast('2016/01/01 11:15:00 AM' as datetime), 50.00),
('ZYA4567', cast('2016/01/01 11:20:00 AM' as datetime), 50.00),
('ZYA4567', cast('2016/01/01 11:25:00 AM' as datetime), 50.00),
('ZYA4567', cast('2016/01/01 11:30:00 AM' as datetime), null),
('ZYA4567', cast('2016/01/01 11:35:00 AM' as datetime), 50.00),
('ZYA4567', cast('2016/01/01 11:40:00 AM' as datetime), 50.00),
('ZYA4567', cast('2016/01/01 11:45:00 AM' as datetime), 50.00),
('ZYA4567', cast('2016/01/01 11:50:00 AM' as datetime), null),
('ZYA4567', cast('2016/01/01 11:55:00 AM' as datetime), null),
('ZYA4567', cast('2016/01/01 12:00:00 PM' as datetime), 50.00),
('ZYA4567', cast('2016/01/01 12:05:00 PM' as datetime), null),
('ZYA4567', cast('2016/01/01 12:10:00 PM' as datetime), null),
('ZYA4567', cast('2016/01/01 12:15:00 PM' as datetime), null),
('ZYA4567', cast('2016/01/01 12:20:00 PM' as datetime), null),
('ZYA4567', cast('2016/01/01 12:25:00 PM' as datetime), 40.00),
('ZYA4567', cast('2016/01/01 12:30:00 PM' as datetime), 50.00)

因此,我希望将每个名称和空值分组,并找出空值出现的最小和最大次数,并清除任何噪音。

我找到了在T-SQL中实现这一目标的最佳方法。但在我们到达之前请注意,行间隔为5分钟,对于此示例,我只想确定名称大于10分钟的日期范围。

我的查询将使我想要达到的目标变得更加明确:

declare @sampletime_interval int = 5
declare @noise_interval int = 10

;with a as
(
    select 
        name,
        sampletime,
        samplevalue,
        row_number() over (partition by name order by name, sampletime)    as rownum
    from #sampledata where samplevalue is null
)
select 
    b.name,
    min(b.sampletime) as startdate,
    max(b.sampletime) as enddate    
from
(
    select 
        a.name,
        a.sampletime,
        sum(case when datediff(minute, a1.sampletime, a.sampletime) >     @sampletime_interval then 1 else 0 end)    
        over (partition by a.name order by a.name, a.sampletime) as block
    from a left join a as a1 on a.name = a1.name and a.rownum =     a1.rownum + 1
) as b group by b.name, b.block 
having datediff(minute, min(b.sampletime), max(b.sampletime)) >=     @noise_interval
order by b.name, min(b.sampletime)

这是我到目前为止使用的LINQ,它并不多,但我不知道该怎么做:

sum(case when datediff(minute, a1.sampletime, a.sampletime) > @sampletime_interval then 1 else 0 end)    
    over (partition by a.name order by a.name, a.sampletime) as block

having datediff(minute, min(b.sampletime), max(b.sampletime)) >=    @noise_interval

LINQ C#:

// Fetch the data with samplevalue as null and put in memory.
var q1 = (from s in sampledata where samplevalue == null).ToList();

// Apply the row_number() over (partition by name order by name, sampletime)
var q2 = q1.OrderBy(x => x.Name)
    .ThenBy(x => x.SampleTime)
    .GroupBy(x => x.Name)
    .Select(g => new { Group = g, Count = g.Count() })
    .SelectMany(g => g.Group.Select(b => b)
    .Zip(Enumerable.Range(1, g.Count), (j, i) =>
    new 
    {
        Name = j.Name,
        SampleTime = j.SampleTime,
        SampleValue = j.SampleValue,
        RowNum = i
    }));

但我不知道从哪里开始。我在这里查看了分区运算符,但不清楚如何将它们应用于我的情况。

https://code.msdn.microsoft.com/LINQ-Partitioning-Operators-c68aaccc

T-SQL(使用SQL Server 2012)的预期输出应为:

enter image description here

0 个答案:

没有答案