SQL连接两个表,只获取第二个表的最新条目

时间:2016-10-08 14:18:13

标签: mysql sql join

我有这两个表:

itemname  description  belongs
A1        some_text    user1
A2        some_text    user1
A3        some_text    user1
A4        some_text    user1
A5        some_text    user1
A1        some_text    user2
B2        some_text    user2

运动

itemname  start_date  end_date    belongs
A1        2013-02-01  2014-01-12  user1
A1        2014-08-14  NULL        user1
A1        2014-10-15  2015-01-01  user1
A2        2013-08-03  2014-08-14  user1     
A2        2014-08-14  NULL        user1    
A3        2013-08-02  2014-08-20  user1
A3        2013-12-05  2014-01-07  user1
A4        2013-07-15  2014-09-13  user1
A4        2014-09-13  NULL        user1
A5        2013-07-15  2014-09-13  user1
A5        2015-03-11  2016-03-12  user1
A5        2016-03-12  2016-04-13  user1
A1        2015-08-01  2015-08-12  user2
B2        2015-08-13  2015-08-23  user2

我正在玩连接和最大(日期),但没有找到一个有效的解决方案。

user1的结果应如下所示:

itemname  description  belongs  start_date  end_date
A1        some_text    user1    2014-08-14  NULL        
A2        some_text    user1    2014-08-14  NULL       
A3        some_text    user1    2013-08-02  2014-08-20      
A4        some_text    user1    2014-09-13  NULL              
A5        some_text    user1    2016-03-12  2016-04-13       

如果没有行,我需要具有最高(最新,最新)end_date的行(移动):

end_date = NULL

如果有一行end_date = NULL,我需要这一行的那一行。

这里的难点是max(start_date)的排序不起作用,因为有时候在一个项目的另一个时间段内有一个时间段。

我希望你能理解我的问题。

来自德国的问候:)

3 个答案:

答案 0 :(得分:1)

你需要这样的东西

查找每个itemname&的最新开始日期。 belongs组合然后将结果返回到最大开始日期以获得结果

SELECT i.itemname,i.description,i.belongs,m.start_date,m.end_date
FROM   items i
       JOIN movements m
         ON i.itemname = m.itemname
            AND i.belongs = m.belongs
       JOIN (SELECT itemname,
                    belongs,
                    Max(COALESCE(end_date, start_date)) AS max_dt,
                    Max(end_date)                       AS max_end_dat,
                    Max(start_date)                       AS max_start_dat
             FROM   movements
             GROUP  BY itemname,
                       belongs) m1
         ON m1.itemname = m.itemname
            AND m1.belongs = m.belongs
            AND ( ( m.end_date = m1.max_dt
                    AND m1.max_dt = m1.max_start_dat )
                   OR ( m1.max_dt = COALESCE(end_date, m.start_date)
                        AND m1.max_start_dat <> m1.max_dt )
                   OR ( m1.max_dt = m.start_date
                        AND m1.max_end_dat <> m1.max_dt ) )
ORDER  BY i.belongs,
          i.itemname 

更新:

SELECT i.itemname,
       i.description,
       i.belongs,
       m.start_date,
       m.end_date
FROM   items i
       JOIN movements m
         ON i.itemname = m.itemname
            AND i.belongs = m.belongs
       JOIN (SELECT itemname,
                    belongs,
                    Max(start_date) AS max_dat,
                    'st'            AS indi
             FROM   movements
             WHERE  end_date IS NULL
             GROUP  BY itemname,
                       belongs
             UNION ALL
             SELECT itemname,
                    belongs,
                    Max(end_date) AS max_dat,
                    'ed'
             FROM   movements m
             WHERE  NOT EXISTS (SELECT 1
                                FROM   movements m1
                                WHERE  m.itemname = m1.itemname
                                       AND m.belongs = m1.belongs
                                       AND end_date IS NULL)
             GROUP  BY itemname,
                       belongs) m1
         ON m1.itemname = m.itemname
            AND m1.belongs = m.belongs
            AND ( ( m1.max_dat = m.start_date
                    AND indi = 'st' )
                   OR ( m1.max_dat = m.end_date
                        AND indi <> 'st' ) )
ORDER  BY i.belongs,
          i.itemname 

如果RDBMS支持ROW_NUMBER窗口函数或APPLY运算符

,这将非常简单

答案 1 :(得分:1)

从一组记录中选择一条记录: 在所有方法中,您可以与Items表一起加入以获取额外信息。

方法-1使用自联接:

Select a.*  
from yourTable as a
left join YourTable as b
  on b.belongs = a.Belongs
 and b.Item_Name=a.Item_Name
 and b.Start_date>a.Start_Date
where b.Start_Date is null

方法-2,使用MaxDate。

with MaxDate as(
Select belongs, Item_Name, Max(Start_Date) as MaxDate
from yourTable
group by belongs, Item_Number
) select * from MaxDate as a
  inner join YourTable as b 
     on b.belongs=a.belongs 
    and b.Item_Number=a.Item_Number 
    and b.Start_Date=a.MaxDate

方法-3,使用Row_Number标记组中的最后一条记录

with LastRec as(
select *,
Row_Number() over(partition by belongs, Item_number order by Start_date desc) as RN
From yourTable
) select * from LastRec
  where rn=1

方法-4,使用子查询获取组中的最后一条记录。

Select * from your table as a
Where a.StartDate=(Select Max(Start_Date) from yourTable as b Where b.belongs=a.belongs and b.Item_Name=a.Item_Number)

答案 2 :(得分:0)

MySQL目前似乎没有ROW_NUMBER()窗口函数。

但它可以通过变量进行模拟。

在下面的示例中,计算@rn变量。

在MS SQL Server中,将通过ROW_NUMBER() OVER (PARTITION BY itemname,belongs ORDER BY coalesce(end_date,getdate()) desc, start_date desc)代替。

然后由于WHERE子句rn = 1,它将仅返回具有最大end_date的移动,其中null被视为max。

select m.itemname, i.description, m.belongs, m.start_date, m.end_date, m.rn
from (
  select itemname, belongs, start_date, end_date,
  @rn := if(@itemname = itemname and @belongs = belongs, @rn+1,1) as rn,
  @itemname := itemname as i,
  @belongs := belongs as b
  from movements
  order by itemname, belongs, coalesce(end_date,'9999-12-31') desc, start_date desc
) m
left join items i on (m.itemname = i.itemname and m.belongs = i.belongs)
where m.rn = 1 
order by m.itemname, m.belongs