C#中的NTILE函数等效

时间:2018-02-28 06:05:30

标签: c# linq tsql

我需要在C#Linq中实现以下SQL:

SELECT NTILE (3) OVER (ORDER BY TransactionCount DESC) AS A...

除了this之外,我找不到类似问题的任何答案。但是我认为这不是我想要的。

我甚至不知道从哪里开始,如果有人可以请至少给我一个我很感激的起点。

- 编辑 -

试着更好地解释一下。 我有一个商店X,包含交易,项目,单位和其他数据,我从SQL检索并存储在C#中的对象中。

我有一个包含相同数据的所有商店的列表,但在这种情况下,我会从Analysis Services中检索它,因为检索到大量数据(以及其他原因),并将所有商店存储在C#中的另一个对象中。 / p>

所以我需要的是订购清单并找出商店X是否在该清单的前四分之一或第二或第三......

我希望这有助于澄清我想要实现的目标。

谢谢

2 个答案:

答案 0 :(得分:2)

您可以使用GroupBy函数通过基于对象的索引进行分组来完成此操作。考虑一下这样的整数列表: -

List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8 };

您可以先使用Select投影所有元素的索引,最后按其resp分组。指数。在计算索引时,我们可以将它除以NTILE值(在这种情况下为3): -

var result = numbers.Select((v, i) => new { Value = v, Index = i / 3 })
                    .GroupBy(x => x.Index)
                    .Select(x => x.Select(z => z.Value).ToList());

Fiddle.

答案 1 :(得分:2)

我相信没有简单的LINQ等价于NTILE(n)。无论如何,根据你的需要,写一个并不难。

T-SQL文档说

  

将有序分区中的行分配到指定数量的组中。这些组从一开始编号。对于每一行,NTILE返回该行所属的组的编号。

(见here

对于NTILE的粗略实施,您可以使用GroupBy。以下示例使用int[]以简化,但当然您不限于

int n = 4;
int[] data = { 5, 2, 8, 2, 3, 8, 3, 2, 9, 5 };
var ntile = data.OrderBy(value => value)
                .Select((value,index) => new {Value = value, Index = index})
                .GroupBy(c => Math.Floor(c.Index / (data.Count() / (double)n)), c => c.Value);

首先,我们的data按其值递增排序。如果您没有使用简单的int,这可能类似于store => store.Revenue(假设您希望通过商店的收入获得分位数)。此外,我们将有序数据选择为匿名类型,以包含索引。这是必要的,因为索引是分组所必需的,但似乎GroupBy不支持带索引的lambda,如Select那样。

第三行不太直观,但我会尝试解释:NTILE函数分配组,分配行。要创建n组,我们将N(项目数)除以n以获取每个项目的项目,然后设置当前索引,以确定当前项目在哪个组中是。为了获得正确的群组数量,我必须使每组的项目数量分数并计算出计算的群组数量,但不可否认,这是相当经验的。

ntile将包含n个组,每个组的Key等于组号。每个组都是可枚举的。如果您想确定,如果元素在第二个四分位数中,您可以检查groups.Where(g => g.Key == 1)是否包含该元素。

备注:我用来确定群组的方法可能需要进行一些微调。