合并两个联合表?

时间:2020-06-16 19:22:36

标签: sql sql-server union

我有两个看起来像这样的表。一个拥有“包装”数据,另一个拥有“配方”数据。

Order#   Lot#    Pkg#  Time
----------------------------
188688   PVB079   19   2:34
188688   PVB079   24   3:15
188688   PVB079   18   4:08
188688   PVB079   13   5:02
188688   PVB079   14   5:40
188688   PVB079   16   6:18
188688   PVB079   15   6:48
188688   PVB079   21   7:22
188688   PVB079   17   8:12
Order#  Recipe  Version  Time
------------------------------
188688  EP01     1       2:35
188688  EP01     2       4:09
188688  EP01     3       6:49

我可以将它们联合在一起,并在时间戳之前对其进行排序,以获取类似于以下内容的内容...

Order#   Lot#    Pkg#  Time  Recipe   Version
----------------------------------------------
188688   PVB079   19   2:34   --        --
188688    --      --   2:35   EP01      1
188688   PVB079   24   3:15   --        --
188688   PVB079   18   4:08   --        -- 
188688    --      --   4:09   EP01      2
188688   PVB079   13   5:02   --        --
188688   PVB079   14   5:40   --        --
188688   PVB079   16   6:18   --        --
188688   PVB079   15   6:48   --        --
188688    --      --   6:49   EP01      3
188688   PVB079   21   7:22   --        --
188688   PVB079   17   8:12   --        --

但是,我想将它们组合在一起,以便配方数据与其前面的1个包装和后面的其他包装在同一行。我理想的结果看起来像这样...

Order#   Lot#    Pkg#  PkgTime  Recipe   Version   RecipeTime
---------------------------------------------------------------
188688   PVB079   19   2:34     EP01      1        2:35
188688   PVB079   24   3:15     EP01      1        2:35
188688   PVB079   18   4:08     EP01      2        4:09 
188688   PVB079   13   5:02     EP02      2        4:09
188688   PVB079   14   5:40     EP02      2        4:09
188688   PVB079   16   6:18     EP02      2        4:09
188688   PVB079   15   6:48     EP02      3        6:49
188688   PVB079   21   7:22     EP02      3        6:49
188688   PVB079   17   8:12     EP02      3        6:49

操作上,输入包装(时间戳),然后他们获得配方(时间戳)。但是有时候配方不会改变。因此,他们对以下软件包使用相同的配方,直到配方更改为止。

有可能吗?我怎样才能像这样合并这两个表?

3 个答案:

答案 0 :(得分:1)

根据Gordon Linoff的回答,这似乎与您的问题相符

select p.*, r.*
from package p 
outer apply
  (select top (1) r.*
   from recipe r
   where r.rec_order = p.pkg_order and r.rec_time < isnull((
     select min(p2.pkg_time)
     from package p2
     where p2.pkg_order = p.pkg_order and p2.pkg_time > p.pkg_time       
     ), convert(datetime2, '9999-12-31'))
   order by r.rec_time desc
  ) r
order by pkg_time

答案 1 :(得分:0)

这与union无关。您可以使用横向联接(在SQL Server中使用apply

)轻松完成此操作。
select p.*, r.*
from package p outer apply
     (select top (1) r.*
      from recipe r
      where r.order# = p.order# and r.time > p.time
      order by r.time asc
     ) r;

横向联接就像一个相关的子查询,可以返回多列和多行(尽管在这种情况下,它只返回一行)。

答案 2 :(得分:0)

类似的事情应该起作用:

SELECT
  package.`Order#`,
  package.`Lot#`,
  package.`Pkg#`,
  package.`Time` AS PkgTime,
  recipe.Recipe,
  recipe.`Version`,
  recipe.`Time` AS RecipeTime
FROM (
SELECT
  p.`Order#` AS keyOrder,
  MAX(IF(p.Time < r.Time, p.Time, NULL)) AS startTime,
  COALESCE(MAX(IF(p.Time < r2.Time, p.Time, NULL)), MAX(p.Time)+1 ) AS endTime,
  r.`Version` AS keyRecipeVersion,
  r.Time AS r1t,
  r2.Time AS r2t
FROM recipe AS r
LEFT JOIN recipe AS r2 ON r2.`Order#` = r.`Order#` AND r2.Version = 1 + r.Version
JOIN package AS p ON p.`Order#` = r.`Order#` -- all packages.  
GROUP BY p.`Order#`, r.`Version`
) AS k
JOIN recipe ON keyOrder = recipe.`Order#` AND keyRecipeVersion = recipe.`Version`
JOIN package ON keyOrder = package.`Order#` 
            AND package.`Time` >= startTime AND package.`Time` < endTime
            -- recipe start is 1 back package time.  
;

这个想法是将您想要的记录提炼为一组“关键字段”,然后可以将它们重新联接回源表。在这种情况下,您的索引编制能力很弱,并且您的数据没有很好的组织,因此有点棘手,功能也不那么强大。

使用OUTER APPLY的另一个答案可能更优雅,我只是想尽可能避免使用非ANSI SQL。

注意:这也可以通过将UNIONGROUP BY包装在一起来完成,但我绝对不建议这样做。 UNION会导致混乱的查询不一致,并且主要用于快速将某些事物拍打在一起。