2017-08-18 132 views
1

在回答一個測試,我遇到以下問題,這點我是不能夠解決:SQL更新查詢利用

如下表Z和查詢:

Table Z: 
| Value | 
--------- 
| 1 | 
| 2 | 
| 3 | 
| 4 | 
--------- 

查詢:

UPDATE Z 
    SET VALUE = Y.VALUE + 1 
    FROM Z AS Y 
    WHERE Y.VALUE = Z.VALUE + 1; 

SELECT SUM(VALUE) FROM Z; 

該問題詢問此查詢執行的結果。這個問題沒有提到特定的SQL語言。

正確答案是16。

我不知道這個查詢如何實現這一結果。我甚至無法在真實環境中執行此查詢,它抱怨「FROM」附近有一些語法錯誤。

1 - 你們知道這個查詢是如何工作的嗎? 2 - 我如何繼續執行此查詢?

P.S.我很難嘗試在UPDATE查詢中找到關於FROM子句的一些信息。

+0

查詢,按原樣,將無法正常工作,甚至在Postgres的,因爲分號的上'SET'語句 – user2877959

+0

抱歉,SET語句中的分號是錯字,已經修復,問題依然存在 –

+0

我看到了。實際上,系統只是在1,2,3上加2,然後對集合進行求和(3,4,5,4)。這裏棘手的部分是where子句是自連接使用Y值,然後加上一個 – xQbert

回答

2

代碼工作的一個數據庫是Postgres。根據RexTester,這確實是答案。

原因應該是因爲您要爲每個匹配的Z值添加「2」:z = y.value + 1 = z.value + 1 + 1 - 但第四個值不匹配。 Postgres產生以下內容:

value 
1 4 
2 3 
3 4 
4 5 

這是相同的數據,只是按不同的順序。

有了類似的聲明,SQL Server做正確的事(我使用的一個FROM條款可怕的逗號,以保持兩個語句儘可能相似)

UPDATE Z 
    SET val = Y.val + 1 
    FROM Z, Z AS Y 
    WHERE Y.val = Z.val + 1; 

它返回:

val 
1 3 
2 4 
3 5 
4 4 

兩個結果集是相同的,他們只是在不同的順序。

+0

在我看來,Postgres和SQL Server正在產生相同的結果。只有在這種情況下,Postgres不會保留原始訂單。在鏈接的RexTester中,如果在生成表第一個表時交換值,最終結果不受影響。 – user2877959

+0

@ user2877959。 。 。謝謝。我確定了答案。我誤解了第一列。 Rextester爲您編號 - 這不是數據中的列。 –

2

我希望這可以幫助(在MSSQL上): 第一個SELECT將顯示更新將使用的原始值。

我在事務/回滾中做了UPDATE,所以它不會改變表。如果要更改數據表,可以刪除BEGIN TRAN和ROLLBACK TRAN。

CREATE TABLE TZ (VALUE INT) 
    INSERT INTO TZ VALUES (1),(2),(3),(4) 

    SELECT Z.VALUE AS Z_VALUE, Y.VALUE AS Y_VALUE 
    FROM TZ Z 
    INNER JOIN TZ Y ON Y.VALUE=Z.VALUE +1 
    ; 

    BEGIN TRAN 
    UPDATE Z SET VALUE=Y.VALUE+1 
    FROM TZ Z 
    INNER JOIN TZ Y ON Y.VALUE=Z.VALUE +1 
    ; 
    SELECT * FROM TZ; 
    SElECT SUM(VALUE) AS TOT FROM TZ; 
    ROLLBACK TRAN 

輸出第一選擇:

更新後
Z_VALUE, Y_VALUE 
1  , 2 
2  , 3 
3  , 4 

輸出選擇的:

VALUE 
3 
4 
5 
4 

所以,實際上SUM 16

1

是如果這個工作,而且我不期望它可以在每個數據庫上進行 - 這可能有助於說明發生了什麼。 Y是隻是Z.的別名在該表中的更新過程中的表和最終結果的加盟:

Z values Y (alias) joined on Z + 1 Update Value Z following update 
======== ========================= ============ ================== 
      1       NO MATCH 
1   2       3    3 
2   3       4    4 
3   4       5    5 
4          NO MATCH  4 
                 (SUM: 16)