2016-02-19 99 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

相關問題