合并两个联合表?

vd2z7a6w  于 2021-07-26  发布在  Java
关注(0)|答案(3)|浏览(289)

我有两张这样的table。一个有“ Package ”数据,另一个有“配方”数据。

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

在操作上,输入一个包(时间戳),然后他们得到一个菜谱(时间戳)。但有时配方不会改变。因此,他们对以下包使用相同的配方,直到配方更改为止。
有可能吗?我怎样才能把这两张table合并成这样?

iecba09b

iecba09b1#

根据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
jm2pwxwz

jm2pwxwz2#

这与 union . 您可以最容易地使用横向联接来完成这项工作,在SQLServer中使用横向联接 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;

横向联接类似于一个相关子查询,它可以返回多个列和多个行(尽管在本例中,它只返回一行)。

3duebb1j

3duebb1j3#

这样的方法应该有用:

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 可能更优雅,我只是想尽量避免使用非ansisql。
注意:这也可以通过 Package UNIONGROUP BY 但我绝对不推荐。 UNION 导致了混乱的不一致的查询,主要是为了快速地将一些东西拼凑在一起。

相关问题