【问题标题】:Group by and MIN() in LINQLINQ中的分组和MIN()
【发布时间】:2013-10-17 10:02:16
【问题描述】:

尝试将以下 SQL 查询转换为 LINQ,但我被 ClientCompany 分组卡住了。

SELECT TOP 300 ClientCompany,
CASE WHEN MIN(FeatureID) = 12 THEN 1 ELSE 0 END as Sort
FROM Ad
LEFT JOIN AdFeature
ON Ad.ID = AdFeature.AdID
WHERE (AdFeature.FeatureID = 13 OR AdFeature.FeatureID = 12)
AND SiteID = 2
GROUP BY ClientCompany
ORDER BY Sort DESC

我尝试将其转换为 LINQ:

(from a in Ads
join af in AdFeatures
on new {
join1 = a.ID,
join3 = 2
} equals new {
join1 = af.AdID,
join3 = af.SiteID
}
let sort = (
af.FeatureID == 12 ? 1 : 0
)
orderby sort descending
where af.FeatureID == 13 || af.FeatureID == 12
select new { a.ClientCompany, sort } ).Take(300)

如何在 LINQ 中使用 MIN(FeatureID)GROUP BY ClientCompany,以便每个 ClientCompany 只返回一行?

编辑

这行得通!基于 Daniel Hilgarth 的回答。这个解决方案有什么地方会出错吗?

Ads.Join(AdFeatures, x => x.ID, x => x.AdID,
(a, af) => new { Ad = a, AdFeature = af })
.Where(x => x.AdFeature.FeatureID == 12 || x.AdFeature.FeatureID == 13)
.Where(x => x.AdFeature.SiteID == 2)
.GroupBy(x => x.Ad.ClientCompany)
.Select(g => new { ClientCompany = g.Key, Sort = g.Min(x => x.AdFeature.FeatureID) == 12 ? 1 : 0 })
.OrderByDescending(x => x.Sort)
.Take(300)

【问题讨论】:

    标签: c# sql linq group-by


    【解决方案1】:

    试试这个:

    Ads.Join(AdFeatures, x => x.FeatureID, x => x.FeatureID,
             (a, af) => new { Ad = a, AdFeature = af })
       .Where(x => x.AdFeature.FeatureID == 12 || x.AdFeature.FeatureID == 13)
       .Where(x => x.AdFeature.SiteID == 2)
       .GroupBy(x => x.Ad.ClientCompany)
       .Select(g => new { ClientCompany = g.Key,
                          Sort = g.Min(x => x.AdFeature.FeatureID) == 12 ? 1 : 0 });
    

    请注意,我将左外连接更改为内连接,因为您的原始查询无条件访问AdFeature,使其有效地成为内连接。

    【讨论】:

    • 所有答案都包含我不太习惯的 lambda 表达式。你能解释一下这里发生了什么吗?当我用 LINQPad 4 尝试它时它不起作用。 'LINQPad.User.Ad' 不包含'Fea​​tureID' 的定义,并且没有扩展方法'FeatureID' 接受'LINQPad.User 类型的第一个参数.Ad' 可以找到(按 F4 添加 using 指令或程序集引用)
    • 进行了一些修改(在原始帖子中更新)。谢谢!
    【解决方案2】:

    你好,我会这样写

                context.Ads.Where(ad => ad.AdFeatures.Any(feature => (feature.FeatureID == 13 || feature.FeatureID == 12) && feature.SiteID == 2))
                       .GroupBy(ad => ad.ClientCompany)
                       .Select(ads => new
                       {
                           cc = ads.Key, sort = ads.SelectMany(ad => ad.AdFeatures)
                                                   .Select(feature => feature.FeatureID)
                                                   .Min() == 12
                       })
                       .OrderBy(arg => arg.sort).Take(300);
    

    【讨论】:

      【解决方案3】:

      试试这个:

      (from a in ads
       join af in AdFeatures on a.ID equals af.AdID into g
       from x in g.DefaultIfEmpty()
       where x.FeatureID == 13 || x.FeatureID == 12
       where x.SiteID == 2
       orderby a.Sort descending
       group a by a.ClientCompany into g2
       from x2 in g2
       let sort = g2.Select(T => T.FeatureID).Min() == 12 ? 1 : 0
       select new { a.ClientCompany, Sort = sort }).Take(300);
      

      为什么还需要分组?

      【讨论】:

      • 分组是为了得到每个公司的最小值。您的查询获得全局最小值,因此它甚至可能是 0。
      猜你喜欢
      • 1970-01-01
      • 2016-10-31
      • 2011-05-01
      • 1970-01-01
      • 2016-07-31
      • 1970-01-01
      • 1970-01-01
      • 2012-09-09
      • 2014-11-21
      相关资源
      最近更新 更多