我有以下SQL查询-包括几个左联接和内部查询,我需要将其转换为LINQ-to-SQL。
INSERT INTO @BranchStatus
SELECT
b.BranchId
,b.BranchName
,AVG(CASE WHEN l.[Status] = 1 THEN DATEDIFF(SECOND, l.AddedTime, GETUTCDATE()) ELSE NULL END) AS CurrentWaitTime
,SUM(CASE WHEN l.[Status] = 1 THEN 1 ELSE 0 END) AS WaitingInLobby
,SUM(CASE WHEN l.[Status] = 5 THEN 1 ELSE 0 END) AS TotalAssists
,SUM(CASE WHEN l.[Status] = 6 THEN 0 ELSE sp.ServiceCount END) AS TotalPSProvided
,AVG(CASE WHEN l.[Status] = 5 THEN DATEDIFF(SECOND, l.AssistedTime, l.CompletedTime) ELSE NULL END) AS AverageAssistTime
,AVG(CASE WHEN l.[Status] = 5 THEN DATEDIFF(SECOND, l.AddedTime, l.AssistedTime) ELSE NULL END) AS AverageWaitTime
,SUM(CASE WHEN l.[Status] = 6 THEN 1 ELSE 0 END) AS TotalAbandons
FROM Branch b
LEFT JOIN Lobby l ON b.BranchId = l.FkBranchId
LEFT JOIN (SELECT FkLobbyId, COUNT(*) AS ServiceCount
FROM ServiceProvided _sp LEFT JOIN [Service] _s ON _sp.FkServiceId=_s.ServiceID
WHERE _s.ShowInMemberLeft=0 AND _sp.FkLobbyId IN
(SELECT LobbyId FROM Lobby WHERE IsActive = 1 AND IsArchived = 0 AND (@BranchIds IS NULL OR FkBranchId in
(SELECT BranchId From @SelectedBranchIds))) GROUP BY _sp.FkLobbyId) sp ON l.LobbyId = sp.FkLobbyId
WHERE
b.IsActive = 1
AND l.IsActive = 1
AND l.IsArchived = 0
AND (@BranchIds IS NULL OR l.FkBranchId in (SELECT BranchId From @SelectedBranchIds))
GROUP BY b.BranchId, b.BranchName
;
以下是LINQ-to-SQL版本:
var branchStatus = (from b in context.Branches.Local join l in context.Lobbies.Local on b.BranchId equals l.BranchId into branchLobbyDetails
from bl in branchLobbyDetails.DefaultIfEmpty()
join ps1 in (from l1 in context.Lobbies.Local
where l1.IsActive && !l1.IsArchived
&& (branches.Count == 0 || branches.Contains(l1.BranchId))
select new
{
l1.LobbyId,
ServiceCount = (from s in context.Services.Local
join sp in context.ServicesProvided.Local on s.ServiceId equals sp.ServiceId
where sp.LobbyId == l1.LobbyId && !s.ShowInLeftWithoutAssist select s.ServiceId).Count()
}) on bl.LobbyId equals ps1.LobbyId
where b.IsActive && bl.IsActive && !bl.IsArchived
&& (branches.Count == 0 || branches.Contains(b.BranchId))
select new BranchStatusDetailsDto
{
Id = b.BranchId.ToString(),
BranchName = b.BranchName,
WaitingInLobby = (from l1 in context.Lobbies.Local where l1.LobbyId == bl.LobbyId && l1.Status == 1 select l1.LobbyId).Count().ToString(),
TotalAssists = (from l1 in context.Lobbies.Local where l1.LobbyId == bl.LobbyId && l1.Status == 5 select l1.LobbyId).Count().ToString(),
TotalAbandons = (from l1 in context.Lobbies.Local where l1.LobbyId == bl.LobbyId && l1.Status == 6 select l1.LobbyId).Count().ToString(),
TotalPSProvided = (from l1 in context.Lobbies.Local where l1.LobbyId == bl.LobbyId && l1.Status != 6 select ps1.ServiceCount).ToString(),
AverageAssistTime = (from l1 in context.Lobbies.Local where l1.LobbyId == bl.LobbyId && l1.Status == 5 select (l1.CompletedTime - l1.AssistedTime).Value.TotalSeconds).Average().ToString(),
AverageWaitTime = (from l1 in context.Lobbies.Local where l1.LobbyId == bl.LobbyId && l1.Status == 5 select (l1.AssistedTime - l1.AddedTime).Value.TotalSeconds).Average().ToString(),
}).ToList();
LINQ在on bl.LobbyId equals ps1.LobbyId
处引发运行时错误,bl为空,这可能是由于左联接所致。如果在where
子句中,则可以像(bl == null ? true : bl.IsActive && !bl.IsArchived )
一样检查null,但不确定如何在联接中做到这一点。
是否有更好的方法编写此查询?