我需要在更新表期间应用一些逻辑。
existing_items 是目标表, received_items 包含对 existing_items 或新项目的更新。
逻辑是 - 对于每个分组的 received_items,应该在 existing_items 中标识一个匹配的行。如果未找到匹配项,则应创建一个新行。
更重要的是行可以匹配多个条件。它们应该始终在代码、line_no(如果给定)、ref(如果给定)上匹配。received_items 行应按 processing_seq 顺序处理,并可能按给定顺序检查匹配项。
当所有分组的 received_item 都与一个 existing_item 匹配时,任何剩余部分都是一个新行。
鉴于:
create table #existing_items(id int identity(1,1), code varchar(10)
,qty numeric(10,2), line_no int, ref varchar(10))
create table #received_items(code varchar(10), qty numeric(10,2), line_no int
,ref varchar(10), processing_seq int)
insert into #existing_items (code, qty, line_no, ref)
values('ABC123',2.0, 1, NULL)
insert into #existing_items (code, qty, line_no, ref)
values('ABC123',3.0, 2, '1001')
insert into #received_items(code, qty, line_no, ref, processing_seq)
values ('ABC123', 4, NULL, NULL, 1)
insert into #received_items(code, qty, line_no, ref, processing_seq)
values ('ABC123', 3, NULL, NULL, 1)
insert into #received_items(code, qty, line_no, ref, processing_seq)
values ('ABC123', 4, NULL, 1002, 2)
insert into #received_items(code, qty, line_no, ref, processing_seq)
values ('ABC123', 4, 2, 1003, 3)
insert into #received_items(code, qty, line_no, ref, processing_seq)
values ('ABC123', 5, NULL, NULL, 4)
从#received_items 中选择 *
ABC123 4.00 NULL NULL 1
ABC123 3.00 NULL NULL 1
ABC123 4.00 NULL 1003 2
ABC123 4.00 2 1002 3
ABC123 5.00 NULL NULL 4
从 #existing_items 中选择 *
1 ABC123 2.00 1 NULL
2 ABC123 3.00 2 1001
结果应该是:
1 ABC123 7.00 1 NULL
2 ABC123 4.00 2 1002
3 ABC123 4.00 3 1003
4 ABC123 5.00 4 NULL
解释:
id=1 的 existing_items 更新为 7,因为 received_items 应该被分组(code、line_no、ref、processing_seq)。该行仅在代码上匹配,因为没有提供 line_no 或 ref。
使用 id=3 创建一个新项目,因为没有找到与 ref 1003 匹配的项目。
id=2 的 existing_items 更新 qty 和 ref,因为在 line_no 上找到了匹配项。
使用 id=4 创建一个新行,因为没有要匹配的行(id=1 已经与 processing_seq = 1 的第一组匹配)。
不知道该怎么做,正在考虑光标,但可能有更简单的方法。我目前正在使用多个自我连接.. 像这样:
Select grp.*
,fm.id as full_match, rm.id as ref_match, lm.id as line_match
,(select min(id) from #existing_items where code = grp.code
and rm.id IS NULL and lm.id IS NULL and fm.id IS NULL and grp.ref IS NULL
) as code_match
-- ,cm.id as code_match
FROM (
select ri.code, sum(ri.qty) qty,ri.line_no,ri.ref, ri.processing_seq
from #received_items ri
group by code, line_no, ref, processing_seq
) grp
LEFT OUTER JOIN
#existing_items fm
ON grp.code = fm.code AND grp.line_no = fm.line_no and grp.ref = fm.ref
LEFT OUTER JOIN
#existing_items rm
ON grp.code = rm.code AND grp.ref = rm.ref
LEFT OUTER JOIN
#existing_items lm
ON grp.code = lm.code AND grp.line_no = lm.line_no
order by grp.processing_seq
这可以部分了解要更新哪一行并产生这个临时结果:
Code Qty Line_No Ref seq fm.id rm.id lm.id cm.id
ABC123 7.00 NULL NULL 1 NULL NULL NULL 1
ABC123 4.00 NULL 1002 2 NULL NULL NULL NULL
ABC123 4.00 2 1003 3 NULL NULL 2 NULL
ABC123 5.00 NULL NULL 4 NULL NULL NULL 1
需要一种方法来识别仅在代码上最接近的匹配,这已经奏效,但不适用于 seq=4 应该具有 NULL 的 cm.id - 所以我需要更改我的子查询以不在同一个子查询中返回先前匹配的 id?然后我应该能够在任何匹配列中没有 id 的地方插入。
任何有关如何解决问题的见解都非常感谢。