【问题标题】:SQL - Tricky MergingSQL - 棘手的合并
【发布时间】:2019-10-22 08:44:48
【问题描述】:

我面临一个棘手的问题。我希望你的专业知识能帮助我解决这个问题。

有2张桌子:

表 1:订单

Index                 ProductName             OrderDate
0                      a                      03/03/1903
1                      a                      10/03/2014
2                      b                      01/01/2017
3                      c                      01/01/2019

表 2:产品规格 --> 此表显示了我们产品颜​​色所做的每一次更改

Index         ProductName                    Color   ColorUpdatedOn
0                      a                     Blue     01/01/1900
1                      a                     Red      01/01/2014
2                      a                     Yellow   01/01/2017
3                      b                     Pink     01/01/2017
4                      c                     Black    01/01/2018
5                      c                     Black    31/12/2018

我希望能够使用 Column Color et UpdatedOn 从 Table1 中检索所有数据

Index   ProductName    OrderDate          Color   ColorUpdatedOn
0        a           03/03/1903           Blue     01/01/1900
1        a           10/03/2014           Red      01/01/2014
2        a           01/01/2019           Yellow   01/01/2017    
3        c           01/01/2019           Black    31/12/2018

你知道我该怎么做吗?

提前感谢您的帮助

拉哥

【问题讨论】:

标签: sql merge


【解决方案1】:

根据颜色获取Product Specs表的max()日期, 然后join 使用year() 函数,适用于mysqlmssql,不确定是否适用于其他数据库。

select o.Index, o.ProdcutName, o.Date, t1.color, t1.ColorUpdatedOn
from Orders o
inner join
    (select color, max(colorupdatedon) as ColorUpdatedOn 
    from productspecs
    group by color) t1 on year(o.OrderDate) = year(t1.createdon)

但我更喜欢使用 right() 函数,因为您的年份日期在末尾。

select o.Index, o.ProdcutName, o.Date, t1.color, t1.ColorUpdatedOn
    from Orders o
    inner join
        (select color, max(colorupdatedon) as ColorUpdatedOn 
        from productspecs
        group by color) t1 on right(o.OrderDate, 4) = right(t1.createdon, 4)

【讨论】:

    【解决方案2】:

    在支持横向连接的数据库中(现在有很多),这很容易:

    select o.*, s.*  -- select the columns you want
    from orders o left join lateral
         (select s.*
          from specs s
          where s.ProductName = o.ProductName and
                s.ColorUpdatedOn <= o.OrderDate 
          order by s.ColorUpdatedOn desc
          fetch first 1 row only
         ) s
         on 1=1;
    

    在 SQL Server 中,这将使用 outer apply 而不是 left join lateral

    在其他数据库中,我会使用lead()

    select o.*, s.*  -- select the columns you want
    from orders o left join
         (select s.*,
                 lead(ColorUpdatedOn) over (partition by ProductName order by ColorUpdatedOn) as next_ColorUpdatedOn
          from specs s
         ) s
         on s.ProductName = o.ProductName and
            o.OrderDate >= s.ColorUpdatedOn and
            (o.OrderDate < s.next_ColorUpdatedOn or s.next_ColorUpdatedOn is null)
    

    【讨论】:

      【解决方案3】:

      假设OrderDateColorUpdatedOn 的数据类型都是date,我们可以找到订购时的颜色。 为此,我使用了分析/窗口功能。 Hive 查询如下所示:

      SELECT 
          y.ProductName, y.OrderDate, y.Color, y.ColorUpdatedOn
      FROM (
          SELECT 
              x.*,
              DENSE_RANK() OVER(PARTITION BY x.ProductName, x.OrderDate ORDER BY x.recency ASC) AS relevance
          FROM (
              SELECT 
                  a.*, b.color, b.ColorUpdatedOn, DATEDIFF(a.OrderDate, b.ColorUpdatedOn) AS recency
              FROM 
                  Order a 
              INNER JOIN 
                  Product b 
              ON (
                  a.ProductName = b.ProductName
                  AND a.OrderDate >= b.ColorUpdatedOn
              )
          ) x 
      ) y
      WHERE 
          y.relevance = 1;
      

      如果您让我知道您正在使用的数据库,则可以进行具体查询。 如果有帮助,请告诉我。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-03-13
        • 2018-03-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-12
        • 2010-11-16
        • 2015-10-14
        相关资源
        最近更新 更多