Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何改进Linq查询(一种数据透视)?_C#_Linq - Fatal编程技术网

C# 如何改进Linq查询(一种数据透视)?

C# 如何改进Linq查询(一种数据透视)?,c#,linq,C#,Linq,我有这个实体: public class Delivery { public int Id { get; set; } public int ProductId { get; set; } public int CustomerId { get; set; } public int Quantity { get; set; } public DateTime DeliveryDate { get; set;

我有这个实体:

public  class Delivery
    {
        public int Id { get; set; }
        public int ProductId { get; set; }
        public int CustomerId { get; set; }
        public int Quantity { get; set; }
        public DateTime DeliveryDate { get; set; }
        public virtual Product Product { get; set; }
        public virtual Customer Customer { get; set; }
    }
我想按周显示交货情况,因此我编写以下查询:

    public override IEnumerable GetModelData(ApplicationDbContext context)
            {
                return context.Deliveries.GroupBy(x => x.Product).Select(x => new
                {
                    Id=x.Key.Id,
                    Product = x.Key.Name,
                    Wk1 =(int?) x.Where(a => SqlFunctions.DatePart("wk", a.DeliveryDate) == 1).Sum(a => a.Quantity),
...
...
...
                    Wk46 = (int?)x.Where(a => SqlFunctions.DatePart("wk", a.DeliveryDate) == 46).Sum(a => a.Quantity),
                    Wk47 = (int?)x.Where(a => SqlFunctions.DatePart("wk", a.DeliveryDate) == 47).Sum(a => a.Quantity),
                    Wk48 = (int?)x.Where(a => SqlFunctions.DatePart("wk", a.DeliveryDate) == 48).Sum(a => a.Quantity),
                    Wk49 = (int?)x.Where(a => SqlFunctions.DatePart("wk", a.DeliveryDate) == 49).Sum(a => a.Quantity),
                    Wk50 = (int?)x.Where(a => SqlFunctions.DatePart("wk", a.DeliveryDate) == 50).Sum(a => a.Quantity),
                    Wk51 = (int?)x.Where(a => SqlFunctions.DatePart("wk", a.DeliveryDate) == 51).Sum(a => a.Quantity),
                    Wk52 = (int?)x.Where(a => SqlFunctions.DatePart("wk", a.DeliveryDate) == 52).Sum(a => a.Quantity),
                }).ToList();
            }
是否可以使用较小的查询获取所需的对象

我现在在delivery数据库表中有大约100个样本行,我有一个填充,即这种获取数据的方法不是最好的


查询正在运行,我只想知道您是否有更好的方法来编写这种查询

使LINQ查询更短的唯一方法是以编程方式生成选择器

但是,确实有一种方法可以使生成的SQL查询更短(更高效)。不要使用翻译不好的
Where(condition).Sum(expr)
构造,而是使用条件Sum,即
Sum(condition?expr:null)
生成更好的SQL:

Wk1 = x.Sum(a => SqlFunctions.DatePart("wk", a.DeliveryDate) == 1 ? a.Quantity : (int?)null),
Wk2 = x.Sum(a => SqlFunctions.DatePart("wk", a.DeliveryDate) == 2 ? a.Quantity : (int?)null),
...

使LINQ查询更短的唯一方法是以编程方式生成选择器

但是,确实有一种方法可以使生成的SQL查询更短(更高效)。不要使用翻译不好的
Where(condition).Sum(expr)
构造,而是使用条件Sum,即
Sum(condition?expr:null)
生成更好的SQL:

Wk1 = x.Sum(a => SqlFunctions.DatePart("wk", a.DeliveryDate) == 1 ? a.Quantity : (int?)null),
Wk2 = x.Sum(a => SqlFunctions.DatePart("wk", a.DeliveryDate) == 2 ? a.Quantity : (int?)null),
...

我会在SQL查询中进行分组,然后在内存中进行数据透视

public static IEnumerable GetModelData(ApplicationDbContext context)
{
    return context.Deliveries
        .GroupBy(x => new { x.Product.Id, x.Product.Name, Week = SqlFunctions.DatePart("wk", x.DeliveryDate) } )
        .Select(x => new
        {
            Id = x.Key.Id,
            Product = x.Key.Name,
            Week = x.Key.Week,
            Quantity = x.Sum(a => a.Quantity),
        })
        .AsEnumerable()
        .GroupBy(x => new { x.Id, x.Product })
        .Select(x => new
        {
            Id = x.Key.Id,
            Product = x.Key.Product,
            Wk1 = x.Sum(a => a.Week == 1 ? a.Quantity : 0),
            Wk2 = x.Sum(a => a.Week == 2 ? a.Quantity : 0),
            Wk51 = x.Sum(a => a.Week == 52 ? a.Quantity : 0),
            Wk52 = x.Sum(a => a.Week == 53 ? a.Quantity : 0),
        })
        .ToList();
}
.AsEnumerable()上方的所有内容都作为一条SQL语句对数据库执行,下方的所有内容都在内存中执行

public static IEnumerable GetModelData(ApplicationDbContext context)
{
    return context.Deliveries
        .GroupBy(x => new { x.Product.Id, x.Product.Name, Week = SqlFunctions.DatePart("wk", x.DeliveryDate) } )
        .Select(x => new
        {
            Id = x.Key.Id,
            Product = x.Key.Name,
            Week = x.Key.Week,
            Quantity = x.Sum(a => a.Quantity),
        })
        .AsEnumerable()
        .GroupBy(x => new { x.Id, x.Product })
        .Select(x => new
        {
            Id = x.Key.Id,
            Product = x.Key.Product,
            Wk1 = x.Sum(a => a.Week == 1 ? a.Quantity : 0),
            Wk2 = x.Sum(a => a.Week == 2 ? a.Quantity : 0),
            Wk51 = x.Sum(a => a.Week == 52 ? a.Quantity : 0),
            Wk52 = x.Sum(a => a.Week == 53 ? a.Quantity : 0),
        })
        .ToList();
}
下面是执行的SQL的跟踪

SELECT
    [GroupBy1].[K1] AS [ProductId],
    [GroupBy1].[K2] AS [Name],
    [GroupBy1].[K3] AS [C1],
    [GroupBy1].[A1] AS [C2]
    FROM ( SELECT
        [Join1].[K1] AS [K1],
        [Join1].[K2] AS [K2],
        [Join1].[K3] AS [K3],
        SUM([Join1].[A1]) AS [A1]
        FROM ( SELECT
            [Extent1].[ProductId] AS [K1],
            [Extent2].[Name] AS [K2],
            DATEPART(wk, [Extent1].[DeliveryDate]) AS [K3],
            [Extent1].[Quantity] AS [A1]
            FROM  [dbo].[Deliveries] AS [Extent1]
            INNER JOIN [dbo].[Products] AS [Extent2] ON [Extent1].[ProductId] = [Extent2].[Id]
        )  AS [Join1]
        GROUP BY [K1], [K2], [K3]
    )  AS [GroupBy1]
如果删除.AsEnumerable(),它将在服务器上全部运行。这是SQL跟踪

SELECT
    [GroupBy2].[K1] AS [ProductId],
    [GroupBy2].[K2] AS [Name],
    [GroupBy2].[A1] AS [C1],
    [GroupBy2].[A2] AS [C2],
    [GroupBy2].[A3] AS [C3],
    [GroupBy2].[A4] AS [C4]
    FROM ( SELECT
        [GroupBy1].[K1] AS [K1],
        [GroupBy1].[K2] AS [K2],
        SUM([GroupBy1].[A1]) AS [A1],
        SUM([GroupBy1].[A2]) AS [A2],
        SUM([GroupBy1].[A3]) AS [A3],
        SUM([GroupBy1].[A4]) AS [A4]
        FROM ( SELECT
            [GroupBy1].[K1] AS [K1],
            [GroupBy1].[K2] AS [K2],
            CASE WHEN (1 = [GroupBy1].[K3]) THEN [GroupBy1].[A1] ELSE 0 END AS [A1],
            CASE WHEN (2 = [GroupBy1].[K3]) THEN [GroupBy1].[A1] ELSE 0 END AS [A2],
            CASE WHEN (52 = [GroupBy1].[K3]) THEN [GroupBy1].[A1] ELSE 0 END AS [A3],
            CASE WHEN (53 = [GroupBy1].[K3]) THEN [GroupBy1].[A1] ELSE 0 END AS [A4]
            FROM ( SELECT
                [Join1].[K1] AS [K1],
                [Join1].[K2] AS [K2],
                [Join1].[K3] AS [K3],
                SUM([Join1].[A1]) AS [A1]
                FROM ( SELECT
                    [Extent1].[ProductId] AS [K1],
                    [Extent2].[Name] AS [K2],
                    DATEPART(wk, [Extent1].[DeliveryDate]) AS [K3],
                    [Extent1].[Quantity] AS [A1]
                    FROM  [dbo].[Deliveries] AS [Extent1]
                    INNER JOIN [dbo].[Products] AS [Extent2] ON [Extent1].[ProductId] = [Extent2].[Id]
                )  AS [Join1]
                GROUP BY [K1], [K2], [K3]
            )  AS [GroupBy1]
        )  AS [GroupBy1]
        GROUP BY [K1], [K2]
    )  AS [GroupBy2]

我会在SQL查询中进行分组,然后在内存中进行数据透视

public static IEnumerable GetModelData(ApplicationDbContext context)
{
    return context.Deliveries
        .GroupBy(x => new { x.Product.Id, x.Product.Name, Week = SqlFunctions.DatePart("wk", x.DeliveryDate) } )
        .Select(x => new
        {
            Id = x.Key.Id,
            Product = x.Key.Name,
            Week = x.Key.Week,
            Quantity = x.Sum(a => a.Quantity),
        })
        .AsEnumerable()
        .GroupBy(x => new { x.Id, x.Product })
        .Select(x => new
        {
            Id = x.Key.Id,
            Product = x.Key.Product,
            Wk1 = x.Sum(a => a.Week == 1 ? a.Quantity : 0),
            Wk2 = x.Sum(a => a.Week == 2 ? a.Quantity : 0),
            Wk51 = x.Sum(a => a.Week == 52 ? a.Quantity : 0),
            Wk52 = x.Sum(a => a.Week == 53 ? a.Quantity : 0),
        })
        .ToList();
}
.AsEnumerable()上方的所有内容都作为一条SQL语句对数据库执行,下方的所有内容都在内存中执行

public static IEnumerable GetModelData(ApplicationDbContext context)
{
    return context.Deliveries
        .GroupBy(x => new { x.Product.Id, x.Product.Name, Week = SqlFunctions.DatePart("wk", x.DeliveryDate) } )
        .Select(x => new
        {
            Id = x.Key.Id,
            Product = x.Key.Name,
            Week = x.Key.Week,
            Quantity = x.Sum(a => a.Quantity),
        })
        .AsEnumerable()
        .GroupBy(x => new { x.Id, x.Product })
        .Select(x => new
        {
            Id = x.Key.Id,
            Product = x.Key.Product,
            Wk1 = x.Sum(a => a.Week == 1 ? a.Quantity : 0),
            Wk2 = x.Sum(a => a.Week == 2 ? a.Quantity : 0),
            Wk51 = x.Sum(a => a.Week == 52 ? a.Quantity : 0),
            Wk52 = x.Sum(a => a.Week == 53 ? a.Quantity : 0),
        })
        .ToList();
}
下面是执行的SQL的跟踪

SELECT
    [GroupBy1].[K1] AS [ProductId],
    [GroupBy1].[K2] AS [Name],
    [GroupBy1].[K3] AS [C1],
    [GroupBy1].[A1] AS [C2]
    FROM ( SELECT
        [Join1].[K1] AS [K1],
        [Join1].[K2] AS [K2],
        [Join1].[K3] AS [K3],
        SUM([Join1].[A1]) AS [A1]
        FROM ( SELECT
            [Extent1].[ProductId] AS [K1],
            [Extent2].[Name] AS [K2],
            DATEPART(wk, [Extent1].[DeliveryDate]) AS [K3],
            [Extent1].[Quantity] AS [A1]
            FROM  [dbo].[Deliveries] AS [Extent1]
            INNER JOIN [dbo].[Products] AS [Extent2] ON [Extent1].[ProductId] = [Extent2].[Id]
        )  AS [Join1]
        GROUP BY [K1], [K2], [K3]
    )  AS [GroupBy1]
如果删除.AsEnumerable(),它将在服务器上全部运行。这是SQL跟踪

SELECT
    [GroupBy2].[K1] AS [ProductId],
    [GroupBy2].[K2] AS [Name],
    [GroupBy2].[A1] AS [C1],
    [GroupBy2].[A2] AS [C2],
    [GroupBy2].[A3] AS [C3],
    [GroupBy2].[A4] AS [C4]
    FROM ( SELECT
        [GroupBy1].[K1] AS [K1],
        [GroupBy1].[K2] AS [K2],
        SUM([GroupBy1].[A1]) AS [A1],
        SUM([GroupBy1].[A2]) AS [A2],
        SUM([GroupBy1].[A3]) AS [A3],
        SUM([GroupBy1].[A4]) AS [A4]
        FROM ( SELECT
            [GroupBy1].[K1] AS [K1],
            [GroupBy1].[K2] AS [K2],
            CASE WHEN (1 = [GroupBy1].[K3]) THEN [GroupBy1].[A1] ELSE 0 END AS [A1],
            CASE WHEN (2 = [GroupBy1].[K3]) THEN [GroupBy1].[A1] ELSE 0 END AS [A2],
            CASE WHEN (52 = [GroupBy1].[K3]) THEN [GroupBy1].[A1] ELSE 0 END AS [A3],
            CASE WHEN (53 = [GroupBy1].[K3]) THEN [GroupBy1].[A1] ELSE 0 END AS [A4]
            FROM ( SELECT
                [Join1].[K1] AS [K1],
                [Join1].[K2] AS [K2],
                [Join1].[K3] AS [K3],
                SUM([Join1].[A1]) AS [A1]
                FROM ( SELECT
                    [Extent1].[ProductId] AS [K1],
                    [Extent2].[Name] AS [K2],
                    DATEPART(wk, [Extent1].[DeliveryDate]) AS [K3],
                    [Extent1].[Quantity] AS [A1]
                    FROM  [dbo].[Deliveries] AS [Extent1]
                    INNER JOIN [dbo].[Products] AS [Extent2] ON [Extent1].[ProductId] = [Extent2].[Id]
                )  AS [Join1]
                GROUP BY [K1], [K2], [K3]
            )  AS [GroupBy1]
        )  AS [GroupBy1]
        GROUP BY [K1], [K2]
    )  AS [GroupBy2]

我不明白你的逻辑和代码。你说你想按周显示交货情况。你能详细说明一下吗?什么是
Wk1、Wk2等
?我正在显示一个包含53列的表格,第一列是ProductName,接下来的52列是一年中的几周,从第一周(Wk1)到第52周(wk52)。在上面的查询中,我删除了一些行以显示一个较小的查询。哇,你检查过生成的SQL了吗?由于分组结果上有52个
Where
语句,我认为它是一个怪物。顺便说一句,你用的是什么ORM?我用的是实体框架,是的,是一个巨大的。。。查询:(有任何性能问题吗?最好使用L2E查询获取非数据透视分组数据,并在内存中进行数据透视。我不理解您的逻辑或代码。您说要按周显示交货。您能详细说明一下吗?什么是
Wk1、Wk2等
?我正在显示一个包含53列的表,第一列是ProductName和接下来的52列是一年中的几周,从第1周(wk1)到第52周(wk52)。在上面的查询中,我删除了一些行以显示较小的查询。哇,你检查过生成的SQL吗?我认为它是一个怪物,因为分组结果上有52个
Where
语句。顺便说一句,你使用的是什么ORM?我使用的是实体框架,是一个巨大的…查询:(有任何性能问题吗?最好使用L2E查询获取非数据透视分组数据,并在内存中进行数据透视。