合并两个联合的表?

问题描述 投票:1回答:1

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

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

在操作上,输入一个包裹(时间戳),然后他们得到一个配方(时间戳)。 但有时配方不会改变。因此,他们对下面的包使用相同的配方,直到配方改变。

这可能吗? 如何将这两张表合并成这样?

sql sql-server union
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;

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


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 使得查询乱七八糟的不一致,而且主要是为了快速地拼凑一些东西。


0
投票

根据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
© www.soinside.com 2019 - 2024. All rights reserved.