【问题标题】:Linq query With Sub Query, Count, Max, Sum, left join whith extended on带有子查询、计数、最大值、总和的 Linq 查询,带有扩展的左连接
【发布时间】:2018-07-25 22:06:31
【问题描述】:

我正在尝试创建一个 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) });

谢谢

【问题讨论】:

  • 对不起,但是...where isnull(customer.CardID, '')&gt;''where customer.CardID&gt;'' 不是返回相同的集合吗?我的意思是null 永远不可能是&gt;'',对吧?此外,您如何期望 Max(在 C# 中)返回与 sum(在 SQL 中)相同的内容?最后,MaxDoc = s.Max(a =&gt; a.DocumentNumber)&gt;0?1:0 括号与您似乎想要的不匹配(MaxDoc = s.Max(a =&gt; a.DocumentNumber&gt;0?1:0) 也许?)
  • 我不确定sqlserver的每个数据库是的
  • 我试图获取一些数据以将它们汇总到我的报告中
  • 是的,我评论的第一部分只是指出您的查询可能过于复杂
  • 如果你删除这部分,剩下的不是很简单,我想要客户的数量,活跃的客户和来自积分系统的折扣总和

标签: c# sql linq


【解决方案1】:

查询应该是:

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]

英孚“经典”反而可以翻译它:

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“经典”中,LEFT JOINON 条件被转换为单个条件(OidFinalizedDate 检查),而在 EF Core 中它们被拆分。

【讨论】:

  • 我有 Xpo 它不支持这个,但接受你的回答是公平的
  • @kosmaskaf Xpo 是什么?
  • Devexpress 的 ORM
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-03
  • 1970-01-01
  • 2019-05-24
  • 2017-08-17
  • 2014-12-01
  • 1970-01-01
相关资源
最近更新 更多