我有一个具有以下结构的数据表:
Foo1 Foo2 Value
A 2 5
B 4 20
C 6 30
B 6 4
我还有一个列表如下:
Foobar
Foo1
A
B
Other
Foo2
4
6
Other
(注意:foobar中将有未知数量的列/条目)
我需要遍历我的列表,并为每个元素找到数据表中与子元素值匹配的平均值。例如,在Foo1中,数据表中A的平均值为5,B - 17.5,其他 - 30。
Foobar
Foo1
A (average is 5)
B (average is 17.5)
Other (average is 30)
Foo2
4 (average is 20)
6 (average is 17)
Other (average is 5)
实际上,数据表有大约50列和一些大量的行。我对SQL / LINQ缺乏经验,所以我不确定如何以一种非常慢的方式解决这个问题。特别是对于"其他"桶。我当前的策略是只做一个嵌套的foreach,然后是LINQ查询来选择与当前子元素匹配的值,并进行平均。像这样:
foreach (var foo in foobar)
{
foreach (var bucket in foo.buckets)
{
var hits = myDataTable.Where(n => n[foo.name].ToString() == bucket.name);
if (hits.Any())
{
bucket.average = hits.Select(x => x["Value"]).Average();
}
}
}
但是,它很慢。是因为这是在LINQ中,还是因为我这样做的方式很差?
修改
我做了一些改进速度,但速度仍然很慢。
foreach (var foo in foobar)
{
var pairs = myDataTable.Select(
n => new {Name = n[foo.name], Value = n["Value"]});
foreach (var bucket in foo)
{
var temp = pairs.Where(n => bucket.name == n.Name);
bucket.average = temp.Any() ? temp.Select(x => x.Value).Average() : 0;
}
}
答案 0 :(得分:5)
它非常慢,因为每次到达最里面的行时您都会进行查询,因此您不必在1个查询中获得所需内容,而是获得N个查询&到数据库(N是foobar.Count * foo.buckets.Count)
这可能不是您的整个代码(将某些内容存储到本地变量中并对其执行任何操作)请发布您的整个方法,我们很乐意为您提供更快的替代方案。
答案 1 :(得分:2)
这样的事情应该能够在Linq中得到你想要的所有结果。
var res1 = from f in foo1
group f by f.Name into g
select new {Name = "Foo1 " + g.Key, Avg = g.Average(v=>v.Value)};
var res2 = from f in foo2
group f by f.Name into g
select new {Name = "Foo2 " + g.Key, Avg = g.Average(v=>v.Value)};
var result = res1.Union(res2).OrderBy(r=>r.Name);
编辑:
因为foo1
和foo2
都在同一个表格中,所以你可以这样做
var res1 = from t in table
group t by t.Foo1 into g
select new {Name = "Foo1 " + g.Key, Avg = g.Average(v=>v.Value)};
var res2 = from t in table
group t by t.Foo2 into g
select new {Name = "Foo2 " + g.Key, Avg = g.Average(v+>v.Value)};
var result = res1.Union(res2).OrderBy(r=>r.Name);
答案 2 :(得分:1)
个人而言,我永远不会让任何人遍历行!这是访问数据库中数据的最糟糕方式。
sql Query将是:
select 'Foo1' as FooName, foo1, avg(value)
from mytable
group by Foo1
UNion all
select 'Foo2' as FooName, foo2, avg(value)
from mytable
group by 2
不确定如何将其转换为linq。你没有说你有什么db后端,但这个是针对SQL服务器的。我想大多数其他dbs都有类似的平均功能,但它可能不完全相同。 然后使用用户界面来操纵数据的显示方式。