【问题标题】:How to limit an SQL query to return at most one of something?如何限制 SQL 查询最多返回一个?
【发布时间】:2010-08-13 02:37:06
【问题描述】:

我的数据库中有一个代表软件版本的表;架构的相关列如下:

ProductID   int
PlatformID  tinyint
Date        datetime

全部不为空,前两列还有一个唯一键。

我想构建一个查询(使用 LINQ),它返回每个平台 (PlatformID) 的最新版本(例如日期),但每个平台不超过一条记录 (PlatformID),并且按日期降序排列。

我该怎么做?


编辑:这是我使用的解决方案:

var product = ...;

var latestReleases = product.Releases
    .GroupBy(p => p.PlatformID)
    .Select(group => group.OrderByDescending(p => p.Date).FirstOrDefault())
    .OrderByDescending(release => release.Date)

为了清楚起见...

foreach (var release in latestReleases)
{
    Console.WriteLine("The latest release of MyProduct for {0} is {1}.",
        release.PlatformID, // of course this would be a string in real code ;)
        release.Version);
}

【问题讨论】:

    标签: c# sql sql-server linq


    【解决方案1】:

    我认为以下代码可以满足您的要求:

    var latestProducts = db.Releases
        .GroupBy(p => p.PlatformID)
        .Select(grp => new {
            Platform = grp.Key,
            Latest = grp.OrderByDescending(p => p.Date).FirstOrDefault()
        })
        .OrderByDescending(entry => entry.Latest.Date);
    
    foreach (var entry in latestProducts)
    {
        Console.WriteLine("The latest product for platform {0} is {1}.",
            entry.Platform,
            entry.Latest.ProductID);
    }
    

    它是这样工作的:

    • 首先,拿走所有产品
    • 按通用 PlatformID 将它们分组
    • 在每个组中,按日期降序对该组中的产品进行排序,然后选择第一个(即日期最晚的那个)
    • 为每个组创建一个包含 PlatformID 和平台最新产品的对象
    • 按日期降序对该对象列表进行排序。

    【讨论】:

    • 蒂姆维,非常感谢您的帮助。虽然您的答案并不完全正确(我认为您正在尝试获取平台 X 的最新发布产品,而我想要每个平台的产品 X 的最新版本),但我仍然接受了它,因为我能够使用它作为我在上面帖子中使用的代码的基础。想一想,您的代码可能对广告很有用……“查看我们最新的 版本!” ;)
    • @Jake Petroules:谢谢。总的来说,我的代码是正确的;我只是不知道你们围绕产品和发布的架构结构。你的问题没有说明。所以我假设有一个包含所有版本的Products 表。
    • 是的,我应该更具体一点,抱歉。 ;)
    【解决方案2】:
                    from plat in 
                    (
                        from p in Products
                        group p by p.PlatformID
                    )
    
                    let latestRelease = 
                    (
                        from p in plat
                        orderby p.Date descending
                        select p
                    ).FirstOrDefault()
    
                    where latestRelease != null
    
                    select new 
                    {
                        PlatformID = plat.Key,
                        LatestProductID = latestRelease.ProductID,
                        LatestDate = latestRelease.Date
                    }
    

    【讨论】:

      【解决方案3】:

      一行代码:

      IEnumerable<Product> products = AllProducts.GroupBy(p => p.PlatformID, 
          (pid, source) => source.Where(p => p.PlatformID == pid).OrderByDescending(p => p.Date).FirstOrDefault());
      

      【讨论】:

      • 嗯,如果你熟悉这个重载方法,我觉得真的没那么难读。
      【解决方案4】:

      如果您使用的是 LINQ to Entities、LINQ to SQL 等,那么只需使用First()FirstOrDefault(),它们会足够聪明地将查询限制为 1。如果您希望更明确,可以将Take(1) 添加到您的查询中。

      【讨论】:

      • 虽然正确,但并未解决实际问题
      猜你喜欢
      • 2011-09-05
      • 1970-01-01
      • 2014-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-11
      • 1970-01-01
      相关资源
      最近更新 更多