第一部分很简单。 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 查询相同。