簡體   English   中英

Linq 查詢 Row_Number() over (按多列排序分區)

[英]Linq query for Row_Number() over (partition by multiple column order by)

I have a SQL Server table having data as shown below and I need a C# Linq query for SQL Server's Row_Number() over (partition by multiple column) windowing function. 任何幫助,將不勝感激

表數據:

位置標識 承包商編號 資源ID 英石 舊約 DT 成本日期 AFEID
15 17570 37450 48.22 66.78 96.44 2022-07-20 1093
15 17570 37450 35.46 49.11 70.92 2022-07-21 1093
15 17570 37450 54.60 75.62 109.20 2022-07-19 1093
15 17570 37450 53.90 74.64 107.80 2022-07-20 1093
15 17571 37450 25.53 35.36 51.06 2022-07-20 1093
15 17571 37625 70.92 98.21 141.84 2022-07-20 1093
15 17571 37450 87.93 121.78 175.86 2022-07-20 1093
15 17571 37450 51.06 70.71 102.12 2022-07-19 1093
15 17570 37680 60.99 84.46 121.98 2022-07-20 1093
15 17570 37680 53.90 74.64 107.80 2022-07-19 1093
15 17570 37478 53.90 74.64 107.80 2022-07-19 1093

SQL查詢需要轉換為Linq:

SELECT  
    LocationID,
    AFEID,
    ContractorID,
    ResourceID,
    MAX(ST) AS MaxST,
    MAX(OT) AS MaxOT,
    MAX(DT) AS MaxDT,
    AVG(ST) AS AvgST,
    AVG(OT) AS AvgOT,
    AVG(DT) AS AvgDT,
    MIN(ST) AS MinST,
    MIN(OT) AS MinOT,
    MIN(DT) AS MinDT,
    CostDate,
    ROW_NUMBER() OVER (PARTITION BY afeid, contractorid, resourceid 
                       ORDER BY costdate DESC) AS rownum              
FROM 
    tbldata 
GROUP BY 
    LocationID, AFEID, ContractorID,
    ResourceID, CostDate

我試過這個 Linq 查詢,但沒有成功:

tbldata.OrderByDescending(x => x.CostDate)
       .AsEnumerable()
       .GroupBy(x => new
       {
           x.LocationId,
           x.AfeId,
           x.ContractorId,
           x.ResourceId,
           x.CostDate,
       })
        .Select(grp => new
        {
            grp.Key.AfeId,
            grp.Key.ContractorId,
            grp.Key.ResourceId,
            grp.Key.LocationId,
            grp.Key.CostDate,
            MaxST = grp.Max(x => x.StandardTime),
            MaxOT = grp.Max(x => x.Overtime),
            MaxDT = grp.Max(x => x.DualTime),
            AvgST = grp.Average(x => x.StandardTime),
            AvgOT = grp.Average(x => x.Overtime),
            AvgDT = grp.Average(x => x.DualTime),
            MinST = grp.Min(x => x.StandardTime),
            MinOT = grp.Min(x => x.Overtime),
            MinDT = grp.Min(x => x.DualTime),
            count = grp.Count(),
            rownum = grp.Zip(Enumerable.Range(1, grp.Count()), (j, i) => new { rownum = i}).FirstOrDefault()
        });

Output 需要使用 Linq 查詢:

行數 位置 ID FEID 承包商編號 資源ID 最大ST MaxOT 最大DT 平均時間 平均OT 平均DT 明斯特 MinOT 明德 成本日期
1 15 1093 17570 37450 35.46 49.11 70.92 35.460000 49.11 70.920 35.46 49.11 70.92 2022-07-21
2 15 1093 17570 37450 53.90 74.64 107.80 51.060000 70.71 102.12 48.22 66.78 96.44 2022-07-20
3 15 1093 17570 37450 54.60 75.62 109.20 54.600000 75.62 109.20 54.60 75.62 109.20 2022-07-19
1 15 1093 17570 37478 53.90 74.64 107.80 53.900000 74.64 107.80 53.90 74.64 107.80 2022-07-19
1 15 1093 17570 37680 60.99 84.46 121.98 60.990000 84.46 121.98 60.99 84.46 121.98 2022-07-20
2 15 1093 17570 37680 53.90 74.64 107.80 53.900000 74.64 107.80 53.90 74.64 107.80 2022-07-19
1 15 1093 17571 37450 87.93 121.78 175.86 56.730000 78.57 113.46 25.53 35.36 51.06 2022-07-20
2 15 1093 17571 37450 51.06 70.71 102.12 51.060000 70.71 102.12 51.06 70.71 102.12 2022-07-19
1 15 1093 17571 37625 70.92 98.21 141.84 70.920000 98.21 141.84 70.92 98.21 141.84 2022-07-20

請幫幫我。

如果我正確理解需要獲得什么,它已被簡化以說明解決方案:

using System.Collections.Generic;
using Xunit;
using System.Linq;

namespace TestProject1
{
    public class TestGrouping
    {
        [Fact]
        public void Test()
        {
            var data = new List<Item>{
                new Item{Location = "A", Contractor = "John", SomeValue = 10},
                new Item{Location = "A", Contractor = "John", SomeValue = 12},
                new Item{Location = "B", Contractor = "John", SomeValue = 10},
                new Item{Location = "C", Contractor = "Tomm", SomeValue = 13},
            };

            var res =
                data
                    .GroupBy(
                        item => new { Location = item.Location },
                        (key, group) =>
                            group.Select((x, i) =>
                                new
                                {
                                    Row = i + 1,
                                    x.Location,
                                    x.Contractor,
                                    SumOfSomeValue = group.Sum(x => x.SomeValue)
                                }))
                    .SelectMany(reportItem => reportItem)
                    .ToList();
        }
    }

    public class Item
    {
        public string Location;
        public string Contractor;
        public int SomeValue;
    }
}

Linq中的q代表查詢。 這並不意味着修改數據。 請參閱下面的解決方案

using System;
using System.Linq;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Data;

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            DataTable tbldata = new DataTable();
            tbldata.Columns.Add("locationid", typeof(int));
            tbldata.Columns.Add("ContractorID", typeof(int));
            tbldata.Columns.Add("ResourceID", typeof(int));
            tbldata.Columns.Add("ST", typeof(decimal));
            tbldata.Columns.Add("OT", typeof(decimal));
            tbldata.Columns.Add("DT", typeof(decimal));
            tbldata.Columns.Add("CostDate", typeof(DateTime));
            tbldata.Columns.Add("AFEID", typeof(int));

            tbldata.Rows.Add(15, 17570, 37450, 48.22, 66.78, 96.44, DateTime.Parse("2022 - 07 - 20"), 1093);
            tbldata.Rows.Add(15, 17570, 37450, 35.46, 49.11, 70.92, DateTime.Parse("2022 - 07 - 21"), 1093);
            tbldata.Rows.Add(15, 17570, 37450, 54.60, 75.62, 109.20, DateTime.Parse("2022 - 07 - 19"), 1093);
            tbldata.Rows.Add(15, 17570, 37450, 53.90, 74.64, 107.80, DateTime.Parse("2022 - 07 - 20"), 1093);
            tbldata.Rows.Add(15, 17571, 37450, 25.53, 35.36, 51.06, DateTime.Parse("2022 - 07 - 20"), 1093);
            tbldata.Rows.Add(15, 17571, 37625, 70.92, 98.21, 141.84, DateTime.Parse("2022 - 07 - 20"), 1093);
            tbldata.Rows.Add(15, 17571, 37450, 87.93, 121.78, 175.86, DateTime.Parse("2022 - 07 - 20"), 1093);
            tbldata.Rows.Add(15, 17571, 37450, 51.06, 70.71, 102.12, DateTime.Parse("2022 - 07 - 19"), 1093);
            tbldata.Rows.Add(15, 17570, 37680, 60.99, 84.46, 121.98, DateTime.Parse("2022 - 07 - 20"), 1093);
            tbldata.Rows.Add(15, 17570, 37680, 53.90, 74.64, 107.80, DateTime.Parse("2022 - 07 - 19"), 1093);
            tbldata.Rows.Add(15, 17570, 37478, 53.90, 74.64, 107.80, DateTime.Parse("2022 - 07 - 19"),  1093);

            var groupTable = tbldata.AsEnumerable()
                .OrderByDescending(x => x.Field<DateTime>("CostDate"))
                .GroupBy(x => new
                {
                    lid = x.Field<int>("LocationId"),
                    afeid = x.Field<int>("AFEID"),
                    cid = x.Field<int>("ContractorId"),
                    rid = x.Field<int>("ResourceId"),
                });


            DataTable output = tbldata.Clone();
            output.Columns.Add("MaxST", typeof(decimal));
            output.Columns.Add("MaxOT", typeof(decimal));
            output.Columns.Add("MaxDT", typeof(decimal));
            output.Columns.Add("AvgST", typeof(decimal));
            output.Columns.Add("AvgOT", typeof(decimal));
            output.Columns.Add("AvgDT", typeof(decimal));
            output.Columns.Add("MinST", typeof(decimal));
            output.Columns.Add("MinOT", typeof(decimal));
            output.Columns.Add("MinDT", typeof(decimal));
            output.Columns.Add("rownum");
            output.Columns["rownum"].SetOrdinal(0);
            output.Columns.Remove("ST");
            output.Columns.Remove("OT");
            output.Columns.Remove("DT");

            foreach (var row in groupTable)
            {
                var dates = row.GroupBy(x => x.Field<DateTime>("CostDate")).ToArray();

                for(int i = 0; i < dates.Count(); i++)
                {
                    DataRow newRow = output.Rows.Add(new object[]
                    {
                        i + 1,
                        row.Key.lid,
                        row.Key.cid,
                        row.Key.rid,
                        dates[i].Key,
                        row.Key.afeid,
                        dates[i].Max(x => x.Field<decimal>("ST")),
                        dates[i].Max(x => x.Field<decimal>("OT")),
                        dates[i].Max(x => x.Field<decimal>("DT")),
                        dates[i].Average(x => x.Field<decimal>("ST")),
                        dates[i].Average(x => x.Field<decimal>("OT")),
                        dates[i].Average(x => x.Field<decimal>("DT")),
                        dates[i].Min(x => x.Field<decimal>("ST")),
                        dates[i].Min(x => x.Field<decimal>("OT")),
                        dates[i].Min(x => x.Field<decimal>("DT"))
                    });
                }
            }

        }

    }
 
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM