将Sum(case)SQL语句转换为Entity Framework中的LINQ查询

时间:2016-09-20 09:10:34

标签: sql-server entity-framework linq

以下是我想要转换为LINQ查询的SQL查询

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

3 个答案:

答案 0 :(得分:2)

第一部分很简单。 SQL表达式SUM(CASE WHEN condition THEN 1 ELSE 0 END)直接映射到LINQ Sum(condition ? 1 : 0)

更有趣的是SQL表达式COUNT(CASE WHEN condition THEN 1 END。这是COUNT(CASE WHEN condition THEN 1 ELSE NULL END的捷径。现在,考虑到SQL COUNT函数跳过NULL值,LINQ映射可以是Count(condition)Sum(condition ? 1 : 0)。根据我使用EF的经验,后者转换为更好的SQL(前者从源表生成额外的子查询读取),因此我总是更喜欢它在LINQ to Entities查询中。

话虽如此,LINQ查询可能是这样的:

// 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),
    };

,生成的SQL如下所示:

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]

正如您所看到的,除了无效的丑陋外部部分之外,最里面的子查询中包含的主要部分几乎与所讨论的SQL查询相同。

答案 1 :(得分:1)

您可以这样做:

   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()
          });

答案 2 :(得分:0)

,