我试图在C#中制作终身价值直方图。
我想将数据分组到10美元的存储桶中。我试图找到一种方法,我不必明确定义每个桶。
输出将是这样的:
Range : Count
0-10 : 23
10-20 : 40
20-30 : 43
等...
我也有会员表;让我说他有两个领域。
int Id
Decimal LifeTimeValue
有没有办法在LINQ中执行此操作,并不要求我明确定义每个存储桶?
这是我迄今为止在SQL中所做的工作。我可以轻松地将其移植到LINQ中,但这是一个糟糕的方法,因为我必须为每个存储桶复制一个when子句。
select
case when LifeTimeValue >= 0 and LifeTimeValue < 10 then ' 0 - 10'
when LifeTimeValue > 10 and LifeTimeValue <= 20 then ' 10+ - 20'
when LifeTimeValue > 20 and LifeTimeValue <= 30 then ' 20+ - 30'
else 'over 30'
end As PriceRange,
count(LifeTimeValue) as ItemTotal
from tblMember
group by
case when LifeTimeValue >= 0 and LifeTimeValue < 10 then ' 0 - 10'
when LifeTimeValue > 10 and LifeTimeValue <= 20 then ' 10+ - 20'
when LifeTimeValue > 20 and LifeTimeValue <= 30 then ' 20+ - 30'
else 'over 30'
end;
答案 0 :(得分:6)
创建直方图时,重要的是覆盖存储桶可能没有数据的情况。对于存储桶0
的结果非常重要。
以桶顺序提供数据也是明智之举。
首先进行查找:
var lookup = context.Member.ToLookup(x => (int)x.LifeTimeValue / 10);
更改为int
允许整数除法生成存储区。
现在我们需要找到数据的范围:
var smallest = lookup.Min(x => x.Key);
var largest = lookup.Max(x => x.Key);
现在查询很简单:
var query =
from x in Enumerable
.Range(smallest, largest - smallest + 1)
select new
{
Range = String.Format("{0}-{1}", x * 10, (x + 1) * 10),
Count = lookup[x].Count(),
};
这是我创建的一些示例数据的结果:
请注意,10-20
范围的计数为0
。
答案 1 :(得分:5)
关键部分是:x.LifeTimeValue - (x.LifeTimeValue % 10)
var query = from x in context.Member
group x by x.LifeTimeValue - (x.LifeTimeValue % 10) into x
select new
{
Range = x.Key,
Count = x.Count()
}