最初の部分は簡単です。 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問合せとほとんど同じです。
良い説明と試してみてください:) – Sampath