Linq查询使用Sub Query,Count,Max,Sum,左连接扩展了

时间:2018-07-25 12:11:56

标签: c# sql linq

我正在尝试创建一个linq查询。

我的SQL查询如下:

select 
    count(*) as Customers, 
    sum(IsActive) ActiveCustomers, 
    Sum(DiscountAmount) DiscountAmount 
from (
    select 
        Customer.Oid,
        Max(Case when DocumentHeader.DocumentNumber>0 then 1 else 0 end) IsActive,
        Sum(DocumentHeader.PointsDiscountAmount) DiscountAmount
    from 
        Customer left join
        DocumentHeader on customer.Oid=DocumentHeader.Customer  and DocumentHeader.FinalizedDate>='20160101' and DocumentHeader.FinalizedDate<='20180131' 
    where isnull(customer.CardID, '')>''
    group by Customer.Oid
) xxx

直到现在我已经尝试过了,但是它没有给我写响应

var result = from customers in Customers 
             where !string.IsNullOrEmpty(customers.CardID)
             join documentHeaders in DocumentHeaders on  customers.Oid  equals documentHeaders.Customer.Oid
             where documentHeaders.FinalizedDate>=apo 
                   && documentHeaders.FinalizedDate<=eos 
                select new
                {
                     Oid = customers.Oid,
                     documentHeaders.DocumentNumber,
                     PromotionValue = documentHeaders.DocumentType.ValueFactor
                 };
return result.GroupBy(g=> new {g.Oid}).Select(s => new { groupid=1, Oid= s.Key.Oid, MaxDoc = s.Max(a => a.DocumentNumber)>0?1:0, PromotionValue = s.Max(a => a.PromotionValue) });

谢谢

1 个答案:

答案 0 :(得分:0)

查询应为:

DateTime startDate = new DateTime(2016, 01, 01);
DateTime endDate = new DateTime(2018, 01, 31);

var result1 = from c in db.Customers
              join d in db.DocumentHeaders.Where(x => x.FinalizedDate >= startDate && x.FinalizedDate <= endDate) on c.Oid equals d.Customer.Oid into dtemp
              from d in dtemp.DefaultIfEmpty()
              where !string.IsNullOrEmpty(c.CardID)
              group d by c.Oid into cd
              select new { Oid = cd.Key, IsActive = cd.Max(x => x.DocumentNumber > 1 ? 1 : 0), DiscountAmount = cd.Sum(x => x.PointsDiscountAmount) };

var result2 = (from x in result1
               group x by 1 into y // see https://stackoverflow.com/a/45144198/613130
               select new { Customers = y.Count(), ActiveCustomers = y.Sum(z => z.IsActive), DiscountAmount = y.Sum(z => z.DiscountAmount) }
               ).FirstOrDefault();

请注意,我将其分为两个嵌套查询(实际上将由LINQ统一)。请参阅有关我在哪里找到有关group x by 1 into y窍门的评论。

已完成的测试表明,EF Core仍不足以进行此查询:从group by到此,一切都在本地完成,因此大量数据在SQL Server和.NET之间移动:

SELECT [c2].[Oid], [c2].[CardID], [t2].[Oid], [t2].[CustomerOid], [t2].[DocumentNumber], [t2].[FinalizedDate], [t2].[PointsDiscountAmount]
FROM [Customers] AS [c2]
LEFT JOIN (
    SELECT [x2].[Oid], [x2].[CustomerOid], [x2].[DocumentNumber], [x2].[FinalizedDate], [x2].[PointsDiscountAmount]
    FROM [DocumentHeaders] AS [x2]
    WHERE ([x2].[FinalizedDate] >= @__startDate_0) AND ([x2].[FinalizedDate] <= @__endDate_1)
) AS [t2] ON [c2].[Oid] = [t2].[CustomerOid]
WHERE [c2].[CardID] IS NOT NULL AND (([c2].[CardID] <> N'') OR [c2].[CardID] IS NULL)
ORDER BY [c2].[Oid]

EF“经典”可以翻译:

SELECT 
    [Limit1].[C1] AS [C1], 
    [Limit1].[C2] AS [C2], 
    [Limit1].[C3] AS [C3], 
    [Limit1].[C4] AS [C4]
    FROM ( SELECT TOP (1) 
        [GroupBy2].[K1] AS [C1], 
        [GroupBy2].[A1] AS [C2], 
        [GroupBy2].[A2] AS [C3], 
        [GroupBy2].[A3] AS [C4]
        FROM ( SELECT 
            [Project1].[K1] AS [K1], 
            COUNT([Project1].[A1]) AS [A1], 
            SUM([Project1].[A2]) AS [A2], 
            SUM([Project1].[A3]) AS [A3]
            FROM ( SELECT 
                1 AS [K1], 
                1 AS [A1], 
                [Project1].[C1] AS [A2], 
                [Project1].[C2] AS [A3]
                FROM ( SELECT 
                    [GroupBy1].[A1] AS [C1], 
                    [GroupBy1].[A2] AS [C2]
                    FROM ( SELECT 
                        [Filter1].[K1] AS [K1], 
                        MAX([Filter1].[A1]) AS [A1], 
                        SUM([Filter1].[A2]) AS [A2]
                        FROM ( SELECT 
                            [Extent1].[Oid] AS [K1], 
                            CASE WHEN ([Extent2].[DocumentNumber] > 1) THEN 1 ELSE 0 END AS [A1], 
                            [Extent2].[PointsDiscountAmount] AS [A2]
                            FROM  [dbo].[Customers] AS [Extent1]
                            LEFT OUTER JOIN [dbo].[DocumentHeaders] AS [Extent2] ON ([Extent2].[FinalizedDate] >= @p__linq__0) AND ([Extent2].[FinalizedDate] <= @p__linq__1) AND ([Extent1].[Oid] = [Extent2].[CustomerOid])
                            WHERE  NOT (([Extent1].[CardID] IS NULL) OR (( CAST(LEN([Extent1].[CardID]) AS int)) = 0))
                        )  AS [Filter1]
                        GROUP BY [K1]
                    )  AS [GroupBy1]
                )  AS [Project1]
            )  AS [Project1]
            GROUP BY [K1]
        )  AS [GroupBy2]
    )  AS [Limit1]

请注意,在EF Core中,ON的{​​{1}}条件被转换为单个条件(LEFT JOINOid检查)他们被分裂了。