将复杂的SQL查询转换为LINQ-to-SQL

时间:2019-07-02 11:26:46

标签: sql linq-to-sql subquery

我有以下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,但不确定如何在联接中做到这一点。

是否有更好的方法编写此查询?

0 个答案:

没有答案