C#中的NTILE函数等效

问题描述 投票:2回答:2

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

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

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

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

- 编辑 -

试着更好地解释一下。我有一个Store X,包含Transactions,Items,Units和其他数据,我从SQL检索并存储在C#中的对象中。

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

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

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

谢谢

c# linq tsql
2个回答
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按其值递增。如果你不使用简单的ints,这可能就像store => store.Revenue(假设您希望通过商店的收入获得分位数)。此外,我们将有序数据选择为匿名类型,以包含索引。这是必要的,因为索引是分组所必需的,但似乎GroupBy不支持具有索引的lambdas,正如Select所做的那样。

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

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

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


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.

© www.soinside.com 2019 - 2024. All rights reserved.