我有两个表,看起来像这样。一个表有 "包装 "数据,另一个表有 "配方 "数据。
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
在操作上,输入一个包裹(时间戳),然后他们得到一个配方(时间戳)。 但有时配方不会改变。因此,他们对下面的包使用相同的配方,直到配方改变。
这可能吗? 如何将这两张表合并成这样?
这与 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;
横向连接就像一个相关的子查询,可以返回多列和多行(尽管在这种情况下,它只返回一行)。
类似这样的东西应该可以用。
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。
注:这也可以通过封装在一起的 UNION
与 GROUP BY
但我绝对不会推荐它。 UNION
使得查询乱七八糟的不一致,而且主要是为了快速地拼凑一些东西。
根据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