LINQ 中的多个 Row_number
Multiple Row_number in LINQ
我试着翻译
select *
from (
select *, rng = row_number() over (partition by grp order by id)
from (
select *, grp = row_number() over (order by id) - row_number() over (partition by Name, Status, DateFinished order by id)
from tooling ) g
) gn
where rng = 1
order by id
来自之前的问题 ()
在 Row_number over (Partition by xxx) in Linq? 的帮助下
我得到了翻译其中一个 row_number 的解决方案,但似乎我运气不好,无法成功翻译整个问题?
我的尝试:
Tooling.OrderBy( x => x.Id)
.GroupBy( x => new {x.Name,x.Status,x.DateFinished} )
.Select( group => new { Group = group, Count = group.Count() } )
.SelectMany( groupWithCount =>
groupWithCount.Group.Select( b => b)
.Zip(
Enumerable.Range( 1, groupWithCount.Count ),
( j, i ) => new { j.Name,j.Status, j.DateFinished, RowNumber = i }
)
)
尝试使用另一种方式通过 LINQ 获取结果。获取 ID < 当前 Id 的上一条记录并检查所有字段是否相同:
var Res = Tooling.Where(x=>{ var r = Tooling.Where(y=>y.Id<x.Id).OrderByDescending(y=>y.Id).FirstOrDefault();
if (r==null) return true;
return !((r.Name==x.Name) && (r.Status==x.Status) && (r.DateFinished==x.DateFinished));
})
.OrderBy( x => x.Id)
.Select(x=>x);
UPD: 下面是一个测试例程:
public class TollingRecord
{
public int Id;
public String Name;
public int Status;
public DateTime? DateFinished;
}
...
private static void TestT1()
{
TollingRecord[] Tooling = new TollingRecord[]{ new TollingRecord() {Id=1, Name="Large", Status=0, DateFinished=null },
new TollingRecord() {Id=2, Name="Large", Status=1, DateFinished=null},
new TollingRecord() {Id=3, Name="Small", Status=0, DateFinished=null},
new TollingRecord() {Id=4, Name="Large", Status=2, DateFinished=null},
new TollingRecord() {Id=5, Name="Large", Status=2, DateFinished=null},
new TollingRecord() {Id=6, Name="Large", Status=1, DateFinished=null},
new TollingRecord() {Id=7, Name="Large", Status=1, DateFinished=null},
new TollingRecord() {Id=8, Name="Small", Status=1, DateFinished=DateTime.Now},
};
var Res = Tooling.Where(x=>{ var r = Tooling.Where(y=>y.Id<x.Id).OrderByDescending(y=>y.Id).FirstOrDefault();
if (r==null) return true;
return !((r.Name==x.Name) && (r.Status==x.Status) && (r.DateFinished==x.DateFinished));
})
.OrderBy( x => x.Id)
.Select(x=>x);
foreach (var a in Res)
{
Console.WriteLine("{0}/{1}/{2}", a.Id,a.Name,a.Status);
}
}
输出:
1/Large/0
2/Large/1
3/Small/0
4/Large/2
6/Large/1
8/Small/1
我试着翻译
select *
from (
select *, rng = row_number() over (partition by grp order by id)
from (
select *, grp = row_number() over (order by id) - row_number() over (partition by Name, Status, DateFinished order by id)
from tooling ) g
) gn
where rng = 1
order by id
来自之前的问题 (
在 Row_number over (Partition by xxx) in Linq? 的帮助下
我得到了翻译其中一个 row_number 的解决方案,但似乎我运气不好,无法成功翻译整个问题?
我的尝试:
Tooling.OrderBy( x => x.Id)
.GroupBy( x => new {x.Name,x.Status,x.DateFinished} )
.Select( group => new { Group = group, Count = group.Count() } )
.SelectMany( groupWithCount =>
groupWithCount.Group.Select( b => b)
.Zip(
Enumerable.Range( 1, groupWithCount.Count ),
( j, i ) => new { j.Name,j.Status, j.DateFinished, RowNumber = i }
)
)
尝试使用另一种方式通过 LINQ 获取结果。获取 ID < 当前 Id 的上一条记录并检查所有字段是否相同:
var Res = Tooling.Where(x=>{ var r = Tooling.Where(y=>y.Id<x.Id).OrderByDescending(y=>y.Id).FirstOrDefault();
if (r==null) return true;
return !((r.Name==x.Name) && (r.Status==x.Status) && (r.DateFinished==x.DateFinished));
})
.OrderBy( x => x.Id)
.Select(x=>x);
UPD: 下面是一个测试例程:
public class TollingRecord
{
public int Id;
public String Name;
public int Status;
public DateTime? DateFinished;
}
...
private static void TestT1()
{
TollingRecord[] Tooling = new TollingRecord[]{ new TollingRecord() {Id=1, Name="Large", Status=0, DateFinished=null },
new TollingRecord() {Id=2, Name="Large", Status=1, DateFinished=null},
new TollingRecord() {Id=3, Name="Small", Status=0, DateFinished=null},
new TollingRecord() {Id=4, Name="Large", Status=2, DateFinished=null},
new TollingRecord() {Id=5, Name="Large", Status=2, DateFinished=null},
new TollingRecord() {Id=6, Name="Large", Status=1, DateFinished=null},
new TollingRecord() {Id=7, Name="Large", Status=1, DateFinished=null},
new TollingRecord() {Id=8, Name="Small", Status=1, DateFinished=DateTime.Now},
};
var Res = Tooling.Where(x=>{ var r = Tooling.Where(y=>y.Id<x.Id).OrderByDescending(y=>y.Id).FirstOrDefault();
if (r==null) return true;
return !((r.Name==x.Name) && (r.Status==x.Status) && (r.DateFinished==x.DateFinished));
})
.OrderBy( x => x.Id)
.Select(x=>x);
foreach (var a in Res)
{
Console.WriteLine("{0}/{1}/{2}", a.Id,a.Name,a.Status);
}
}
输出:
1/Large/0
2/Large/1
3/Small/0
4/Large/2
6/Large/1
8/Small/1