只更新连接表中可能有多个相同行的一行?

时间:2016-02-19 19:44:19

标签: sql sql-server

所以这可能会有点复杂,但我试图尽可能地提炼它。基本上我有一个带有'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,但每个插槽只能设置一次,因为相同的插槽/项目组合可能会多次出现。

我已经考虑过这样一种可能性,而不是历史表指向受影响的插槽而是指向受影响的连接表条目,但这需要将一个主键添加到连接表。并不过分喜欢这个想法,但如果绝对必要,可以这样做。我宁愿找到一个解决方案,我不必在连接表中添加主键,尽管如果可能的话。

1 个答案:

答案 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;