Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 在可能有多个相同行的联接表中只更新一行?_Sql_Sql Server - Fatal编程技术网

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

Sql 在可能有多个相同行的联接表中只更新一行?,sql,sql-server,Sql,Sql Server,所以这可能有点复杂,但我试着尽可能地提取它。基本上,我有一个带有“items”的表,一个带有“slot”的表,一个连接表,两个插槽之间有“slot\u items”,因为插槽可以有项目,一个“history”表,以防一个项目更改为另一个项目,然后更新“slot\u items”表中的所有链接,还有一个“history\u slots”表,以指示哪些插槽受到项目更改的影响 现在,我正试图找到一种方法来撤销历史变更。如果有人创建了将项目a更改为项目B的历史记录,则插槽1可能已经有了项目B,在这种情况

所以这可能有点复杂,但我试着尽可能地提取它。基本上,我有一个带有“items”的表,一个带有“slot”的表,一个连接表,两个插槽之间有“slot\u items”,因为插槽可以有项目,一个“history”表,以防一个项目更改为另一个项目,然后更新“slot\u items”表中的所有链接,还有一个“history\u slots”表,以指示哪些插槽受到项目更改的影响

现在,我正试图找到一种方法来撤销历史变更。如果有人创建了将项目a更改为项目B的历史记录,则插槽1可能已经有了项目B,在这种情况下,您可能会在联接表中获得两个连接项目B和插槽1的条目。这对我来说很好,因为我可以使用一些简单的分组来确保项目B只返回一次

但是,如果我想撤消历史记录更改,我会尝试找到一种方法,对每个插槽仅更新“插槽\u项”中的第一个实例,其中历史\u插槽项与插槽匹配,history.oldItem与项目匹配。我不想同时更新插槽1项目B的两个实例,因为该插槽上原来有一个项目B。所以我想从插槽1项目B的两个条目返回插槽1项目A和插槽1项目B

不幸的是,我似乎不能简单地更新TOP1。。。因为可能有多个插槽受项目历史记录更改的影响。因此,如果有一个插槽2也有一个更新为项目B的项目a,我想同时恢复该插槽\u项目条目

要将其放在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\u items中的所有条目,以将fk\u items从B设置为A,但每个插槽仅一次,因为同一插槽/项目组合可能会出现多次

我曾经考虑过这样一种可能性,即不是历史表指向受影响的插槽,而是指向受影响的联接表条目,但这需要向联接表添加主键。不太喜欢这个主意,但在绝对必要的情况下可以这样做。如果可能的话,我更愿意找到一种解决方案,不必向联接表中添加主键。

为此,我经常使用row\u number。您需要某种列来指定顺序,因此让我假设一个creationdate列。我发现逻辑和数据很难理解。但是,要将@history\u slots中的最新记录更改为'A':


不完全是。。。我正在尝试更新slot\u项,因此我尝试将您的查询修改为以下内容。。。在cte为SELECT si.*的情况下,按h.id按h.changeDate为seqnum从@history h INNER JOIN@history\U slots hs ON h.id=hs.fk\U history INNER JOIN@slots\U items si ON hs.fk\U slots=si.fk\U slots从cte中选择*行数,其中fk\U items='B'和seqnum=1;这只给出了第一个结果,但我需要所有的结果,其中fk_items='B',但每个槽只有一个实例。
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;