【问题标题】:Select Top 1 From a Table For Each Id in another Table为另一个表中的每个 ID 从表中选择前 1 个
【发布时间】:2011-07-01 16:19:22
【问题描述】:

表结构为:

create table fruit (
  id int identity(1,1),
  name varchar(max)
)

create table fruit_allocation (
  id int identity(1,1),
  fruit_id int references fruit(id),
  customer_id int references store(id),
  amount float,
)

create table measurement (
  fruit_allocation_id int references fruit_allocation(id),
  measurement_date datetime,
  measurement float,
)

每个水果可以分配给多个客户,创建一条fruit_allocation 记录。每个fruit_allocation 记录可以有多个测量值。

我想为给定水果 id 的每个水果分配选择最新的测量值

到目前为止,我有以下内容:

select * 
  from measurement 
 where fruit_allocation_id in (select id 
                                 from fruit_allocation 
                                where fruit_id = 10)

这会返回该水果的所有测量值,我只想为每个fruit_allocation 返回 1 个测量值。

【问题讨论】:

    标签: sql sql-server tsql


    【解决方案1】:

    选择 * 从测量 m 其中measurement_date =(从测量m1中选择前1个measurement_date 其中 m1.fruit_allocation_id = m.fruit_allocation_id 按测量日期顺序排列) 和 fruit_allocation_id in (选择 id 来自水果分配 其中fruit_id = 3)

    【讨论】:

    • 但似乎 cross apply 没有那么重 a 并且可以从 [fruit_allocation] 获取数据 ...
    【解决方案2】:

    你可以CROSS APPLY

    select a.*, m.*
    from fruit_allocation a
    cross apply (
        select top 1 *
        from measurement m
        where m.fruit_allocation_id = a.id
        order by m.measurement_date desc
    ) m
    where a.fruit_id = 10
    

    【讨论】:

    • 您可能会发现关于 APPLY 与 JOIN 的讨论很有趣:stackoverflow.com/q/1139160/4794
    • @Don 仅当 JOIN 可以正常工作时,“vs”才适用。在这种情况下,JOIN 无法计算出correlated TOP 1。但是感谢您链接到 BOL 并阅读全文
    • 有更多创造性的方法使用连接来解决这个问题。 (见我的回答:stackoverflow.com/questions/5073089/…)不过,了解 APPLY 很有趣,而且听起来在这种情况下它可能更有效。
    • 顺便说一句,BOL?是 Book O'Learnin' 吗?
    • @Don - msdn.microsoft.com/en-us/library/ms130214.aspx 的缩写 B oks O n L ine
    【解决方案3】:

    创建一个子查询以查找每个分配的最新测量值,然后加入该子查询,就像它是一个真实的表一样。

    select * from measurement meas
    join
            (
            SELECT  fruit_allocation_id,
                    MAX(measurement_date) as max_date
            FROM    measurement meas2
            JOIN    fruit_allocation alloc
            ON      alloc.id = meas2.fruit_allocation_id
            where fruit_id = 10
            ) max_meas
    on      meas.fruit_allocation_id = max_mes.fruit_allocation_id
    and     meas.measurement_date = max_meas.max_date
    

    【讨论】:

      【解决方案4】:

      假设您使用的是 SQL Server 2005+

      With RankedMeasurements As
          (
          Select M.fruit_allocation_id
              , M.measurement_date
              , M.measurement
              , Row_Number() Over ( Partition By M.fruit_allocation_id 
                                      Order By M.measurement_date Desc ) As Rnk
          From measurement As M
          Where Exists    (
                          Select 1
                          From fruit_allocation As FA1
                          Where FA1.id = M.fruit_allocation_id
                              And FA1.fruit_id = 10
                          )   
          )
      Select RM.fruit_allocation_id
          , RM.measurement_date
          , RM.measurement
      From RankedMeasurements As RM
      Where Rnk = 1
      

      【讨论】:

        猜你喜欢
        • 2012-03-23
        • 2015-04-13
        • 2011-08-23
        • 1970-01-01
        • 2013-09-05
        • 1970-01-01
        • 1970-01-01
        • 2021-01-26
        • 1970-01-01
        相关资源
        最近更新 更多