所以这可能会有点复杂,但我试图尽可能地提炼它。基本上我有一个带有'items'的表,一个带'slots'的表,一个连接表,两个之间的'slots_items',因为插槽可以有项目,一个'history'表,以防一个项目被更改为另一个项目,然后更新'slots_items'表中的所有链接,以及'history_slots'表,以指示哪些插槽受项目更改影响。
现在,我正试图找到一种“撤消”历史变化的方法。如果某人创建了将项目A更改为项目B的历史记录,则插槽1可能已经包含项目B,在这种情况下,您可能会在连接表中获得两个连接项目B和插槽1的条目。这很好(对我而言)因为我可以使用一些简单的分组来确保项目B只返回一次。
但是,如果我想撤消历史记录更改,我正试图找到一种方法来说“只更新'slots_items'中的第一个实例,其中每个插槽的history_slots条目与插槽匹配,而history.oldItem匹配项目“。我不想更新插槽1的两个实例< - >项目B因为实际上 原来是该插槽上的项目B.所以我想从插槽1< - >的两个条目开始。项目B返回到插槽1< - >项目A和插槽1< - >项目B。
不幸的是,我不能(似乎)只是做一个“更新TOP(1)......”,因为可能有多个插槽受到项目历史记录更改的影响。因此,如果有一个插槽2也有一个更新为项目B的项目A,我想同时还原那个slots_items条目。
把它放在SQL中......
DECLARE @items TABLE(
id VARCHAR
);
INSERT INTO @items VALUES('A'),('B'),('C');
DECLARE @slots TABLE(
id INT
);
INSERT INTO @slots VALUES(1),(2),(3);
DECLARE @slots_items TABLE(
fk_slots INT,
fk_items VARCHAR
);
INSERT INTO @slots_items VALUES(1,'B'),(1,'B'),(2,'C'),(2,'B'),(2,'C');
DECLARE @history TABLE(
id INT,
fk_oldItem VARCHAR,
fk_newItem VARCHAR
);
INSERT INTO @history VALUES(100,'A','B');
DECLARE @history_slots TABLE(
fk_history INT,
fk_slots INT
);
INSERT INTO @history_slots VALUES(100,1),(100,2);
因此,在此数据集中(项目更改后),插槽1将包含项目B,B,C,插槽2将包含项目B,C。
我希望能够撤消这个(做一个更新),以便它会读取插槽1有项目A,B,C和插槽2有项目A,C。任何想法/帮助? 编辑以尝试澄清:我希望更新@slots_items中的所有条目,将fk_items从B设置为A,但每个插槽只能设置一次,因为相同的插槽/项目组合可能会多次出现。
我已经考虑过这样一种可能性,而不是历史表指向受影响的插槽而是指向受影响的连接表条目,但这需要将一个主键添加到连接表。并不过分喜欢这个想法,但如果绝对必要,可以这样做。我宁愿找到一个解决方案,我不必在连接表中添加主键,尽管如果可能的话。
答案 0 :(得分:0)
为此,我经常使用row_number()
。您需要某种指定排序的列,因此我假设creationdate
列。我发现很难遵循逻辑和数据。但是,要将@history_slots
中的最新记录更改为'A'
:
with toupdate as (
select hs.*, row_number() over (partition by id order by creationdate desc) as seqnum
from history_slots hs
)
update todupdate
set fk_oldItem = 'A'
where seqnum = 1;