简体   繁体   English

C#中的NTILE函数等效项

[英]NTILE function equivalent in C#

I need to implement the following SQL in C# Linq: 我需要在C#Linq中实现以下SQL:

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

I couldn't find any answer to a similar problem except this . 我找不到任何除外回答类似的问题 However I don't think that is what I am looking for. 但是,我认为这不是我想要的。

I don't even know where to start, if anyone could please give me at least a starting point I'd appreciated. 我什至不知道从哪里开始,如果有人可以,请给我至少一个我很感激的起点。

-- EDIT -- -编辑-

Trying to explain a little better. 试图解释好一点。 I have one Store X with Transactions, Items, Units and other data that I retrieve from SQL and store in a object in C#. 我有一个带有事务,项目,单位和其他数据的Store X,这些数据是从SQL中检索并存储在C#对象中的。

I have a list of all stores with the same data but in this case I retrieve it from Analysis Services due to the large amount of data retrieved (and other reasons) and I store all of it in another object in C#. 我有所有具有相同数据的存储的列表,但是在这种情况下,由于检索到的数据量大(以及其他原因),我从Analysis Services检索了它,并将所有这些存储在C#中的另一个对象中。

So what I need is to order the list and find out if store X is in the top quartile of that list or second or third... 所以我需要对列表进行排序,并找出商店X是否在该列表的前四分之一或第二或第三位...

I hope that helps to clarify what I am trying to achieve. 我希望这有助于阐明我要实现的目标。

Thank you 谢谢

I believe that there is no simple LINQ equivalent of NTILE(n) . 我相信没有NTILE(n)简单LINQ等效项。 Anyway, depending on your needs it's not that hard to write one. 无论如何,根据您的需求写一个并不难。

The T-SQL documentation says T-SQL文档说

Distributes the rows in an ordered partition into a specified number of groups. 将有序分区中的行分布到指定数量的组中。 The groups are numbered, starting at one. 这些组从1开始编号。 For each row, NTILE returns the number of the group to which the row belongs. 对于每一行,NTILE返回该行所属的组的编号。

(see here ) (请参阅此处

For a very crude implementation of NTILE you can use GroupBy . 对于NTILE的非常粗糙的实现,可以使用GroupBy The following example uses an int[] for sake of simplicity, but of course you are not restricted to 为了简单起见,下面的示例使用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);

First, our data is ordered ascending by it's values. 首先,我们的data按其值升序排列。 If you are not using simple int s this could be something like store => store.Revenue (given you'd like to get the quantiles by revenue of the stores). 如果您不使用简单的int则可能类似于store => store.Revenue (假设您希望通过商店的收入获取分位数)。 Futhermore we are selecting the ordered data to an anonymous type, to include the indices. 此外,我们正在选择有序数据为匿名类型,以包括索引。 This is necessary since the indices are necessary for grouping, but it seems as GroupBy does not support lambdas with indices, as Select does. 这是必需的,因为索引对于分组是必需的,但是似乎GroupBy不像Select那样支持带有索引的lambda。

The third line is a bit less intuitive, but I'll try and explain: The NTILE function assigns groups, the rows are assigned to. 第三行不太直观,但是我将尝试解释: NTILE函数分配组,行被分配到。 To create n groups, we devide N (number of items) by n to get the items per group and then device the current index by that, to determine in which group the current item is. 要创建n组,我们将N (项数)除以n来获取每个组的项,然后根据该值来配置当前索引,以确定当前项位于哪个组中。 To get the number of groups right I had to make the number of items per group fractional and floor the calculated group number, but admittedly, this is rather empirical. 为了获得正确的组数,我必须将每个组的项目数小数,然后将计算出的组数设为底数,但是诚然,这是凭经验得出的。

ntile will contain n groups, each one having Key equal to the group number. ntile将包含n组,每个组的Key等于组号。 Each group is enumerable. 每个组都是可枚举的。 If you'd like to determine, if an element is in the second quartile, you can check if groups.Where(g => g.Key == 1) contains the element. 如果要确定某个元素是否在第二个四分位数中,则可以检查groups.Where(g => g.Key == 1)包含该元素。

Remarks: The method I've used to determine the group may need some fine adjustment. 备注:我用来确定组的方法可能需要一些微调。

You can do it using GroupBy function by grouping based on index of the object. 您可以使用GroupBy函数,根据对象的索引进行分组。 Consider a list of integers like this:- 考虑这样的整数列表:

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

You can first project the Index of all elements using Select and finally group by their resp. 您可以先使用“ Select来投影所有元素的索引 ,最后再根据它们的响应进行分组。 index. 指数。 While calculating the Index we can divide it by NTILE value (3 in this case):- 在计算索引时,我们可以将其除以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. 小提琴。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM