Convert Sum(case) SQL statement to LINQ query in Entity Framework

强颜欢笑 提交于 2020-12-14 06:32:52

问题


Below is my SQL query that I'm looking to convert to LINQ query

SELECT 
    ProcessName,
    SUM(CASE WHEN Status = 'In-Progress' THEN 1 ELSE 0 END) As 'In-Progress',
    SUM(CASE WHEN Status = 'Success' THEN 1 ELSE 0 END) As 'Completed',
    Count(CASE WHEN status in ('In-Progress','Success') then 1 end) as Total
FROM
    TableName
GROUP BY 
    ProcessName

回答1:


The first part is easy. The SQL expression SUM(CASE WHEN condition THEN 1 ELSE 0 END) directly maps to the LINQ Sum(condition ? 1 : 0).

More interesting is the SQL expression COUNT(CASE WHEN condition THEN 1 END. It's a shortcut for COUNT(CASE WHEN condition THEN 1 ELSE NULL END. Now, taking into account that SQL COUNT function skips the NULL values, the LINQ mapping could be either Count(condition) or Sum(condition ? 1 : 0). From my experience with EF, the later translates to a better SQL (the former generates additional subquery reading from the source table), so I always prefer it in LINQ to Entities queries.

With that being said, the LINQ query could be something like this:

// constants to avoid typos
const string StatusInProgress = "In-Progress";
const string StatusCompleted = "Success";
// needed for IN clause 
var statuses = new[] { StatusInProgress, StatusCompleted };
// the query
var query =
    from e in db.TableA
    group e by e.ProcessName into g
    select new
    {
        InProgress = g.Sum(e => e.Status == StatusInProgress ? 1 : 0),
        Completed = g.Sum(e => e.Status == StatusCompleted ? 1 : 0),
        C = g.Sum(e => statuses.Contains(e.Status) ? 1 : 0),
    };

and the generated SQL looks like this:

SELECT
    1 AS [C1],
    [GroupBy1].[K1] AS [ProcessName],
    [GroupBy1].[A1] AS [C2],
    [GroupBy1].[A2] AS [C3],
    [GroupBy1].[A3] AS [C4]
    FROM ( SELECT
        [Extent1].[K1] AS [K1],
        SUM([Extent1].[A1]) AS [A1],
        SUM([Extent1].[A2]) AS [A2],
        SUM([Extent1].[A3]) AS [A3]
        FROM ( SELECT
            [Extent1].[ProcessName] AS [K1],
            CASE WHEN (N'In-Progress' = [Extent1].[Status]) THEN 1 ELSE 0 END AS [A1],
            CASE WHEN (N'Success' = [Extent1].[Status]) THEN 1 ELSE 0 END AS [A2],
            CASE WHEN ([Extent1].[Status] IN (N'In-Progress', N'Success')) THEN 1 ELSE 0 END AS [A3]
            FROM [dbo].[TableName] AS [Extent1]
        )  AS [Extent1]
        GROUP BY [K1]
    )  AS [GroupBy1]

As you can see, except the ugly outer parts that do nothing, the main part contained in the innermost subquery is almost identical to the SQL query in question.




回答2:


You may do something like that :

   var statuses = new {"In-Progress","Success"};


var res = yourData
          .GroupBy(m => m.ProcessName)
          .Select(g => new {
             ProcessName = g.Key,

             //for InProgress, 2 (or 3) ways
             InProgress = g.Select(x => x.Status == "In-Progress" ? 1 : 0).Sum(),
             //another way
             InProgress = g.Where(x => x.Status == "In-Progress").Count(),
             //another way, not sure if it works in linq to entities
             InProgress = g.Count(x => x.Status == "In-Progress"),

             //same 3 ways possible for completed, the first here
             Completed = g.Select(x => x.status == "Success" ? 1 : 0).Sum(),

             //for the count
             //not sure if this one works in linq to entities
             Total = g.Count(x => statuses.Contains(x.Status))
             //alternative
             Total = g.Where(x => statuses.Contains(x.Status)).Count()
          });



回答3:


 string statuses = new {"In-Progress","Success"};

var results = from item in TableName
              group item by p.ProcessName into g
              select new yourReturnType 
              { 
                 ProcessName = g.Key,
                 In-Progress = g.Where(l=>l.Status == "In-Progress").Count(),
                 Completed = g.Where(l=>l.Status == "Success").Count(),                     
                 Total = g.Where(x => statuses.Contains(x.Status)).Count()

              };


来源:https://stackoverflow.com/questions/39590025/convert-sumcase-sql-statement-to-linq-query-in-entity-framework

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!