2016-02-19 107 views
0

所以这可能会有点复杂,但我试图尽可能地提取它。基本上我有一个'物品'表,'插槽'的表,一个连接表,'slots_items'表,因为插槽可以有物品,一个'历史'表,以防万一一个物品被改变为另一个物品,然后更新'slots_items'表中的所有链接以及'history_slots'表,以指示哪些插槽受到项目更改的影响。只更新可能存在多个相同行的连接表中的一行?

现在,我试图找到一种方法来“撤消”历史更改。如果有人创建了一个历史记录来将项目A更改为项目B,则有可能插槽1可能已经包含项目B,在这种情况下,您可能会在连接表格中获得两个项目,它们将加入项目B和插槽1.这对我来说很好(对我而言)因为我可以使用一些简单的分组来确保项目B只返回一次。但是,如果我想撤消历史记录更改,我试图找到一种方法来说:“只更新'slots_items'中的第一个实例,其中history_slots条目与slot和history.oldItem相匹配匹配项目“。我不想更新两个插槽1的实例<→项目B,因为实际上原来在该插槽上的项目B.所以我想从两个插槽1 < - >项目B回到插槽1 < - >项目A和插槽1 < - >项目B.

不幸的是,我不能(似乎)只是做一个“UPDATE TOP(1)...”,因为可能有多个插槽受到项目历史更改的影响。所以如果有一个插槽2也有一个项目A更新到项目B,我想还同时恢复该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

我经常为此使用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; 
+0

不太......我想更新slots_items,所以我试图修改查询到以下...'WITH AS CTE( SELECT si。*,row_number()OVER(h.id ORDER BY PARTITION BY h.changeDate)AS seqnum FROM @history h INNER JOIN @history_slots hs ON h.id = hs.fk_history INNER JOIN @slots_items si ON hs.fk_slots = si.fk_slots)SELECT * FROM cte WHERE fk_items ='B'AND seqnum = 1;'这只给了我第一个结果,但我需要所有fk_items ='B'的结果,但每个槽只有一个实例。 – felloffthestack

相关问题