2011-04-01 78 views
4

我有兩個父/子關係的表。我想用孩子的數據更新父母。然而,假設有2個孩子,我希望能夠選擇哪個孩子用於更新,這取決於孩子的其他列。 這是我到目前爲止: 家長:@test 孩子:@exdat 預期的結果,更新後的父級結果應該只包含大寫字母。我想更新與孩子的一些數據父,但如果存在一個以上的,我寧願選擇一個孩子P1超過P2超過P4帶有加入的TSQL更新語句

DECLARE @test TABLE 
(
    id int, 
    val char(1) 
); 
DECLARE @exdat TABLE 
(
    id int, 
    dval char(1), 
    dimp char(2) 
); 
INSERT INTO @test (id,val) 
      SELECT 1,'a' 
    UNION ALL SELECT 2,'b' 
    UNION ALL SELECT 3,'c' 
    UNION ALL SELECT 4,'d' 
    UNION ALL SELECT 5,'e' 
    UNION ALL SELECT 6,'f' 
    UNION ALL SELECT 7,'g' 
; 
INSERT INTO @exdat (id,dval,dimp) 
      SELECT 1,'A','p1' 
    UNION ALL SELECT 2,'B','p3' 
    UNION ALL SELECT 3,'C','p1' 
    UNION ALL SELECT 4,'D','p2' 
    UNION ALL SELECT 5,'E','p2' 
    UNION ALL SELECT 6,'F','p3' 
    UNION ALL SELECT 7,'w','p2' 
    UNION ALL SELECT 7,'g','p3' 
    UNION ALL SELECT 7,'G','p1' 
    UNION ALL SELECT 7,'z','p4' 
; 
UPDATE @test SET 
    val = e.dval 
FROM 
    @test t 
    INNER JOIN @exdat e ON t.id = e.id 
; 
SELECT * FROM @test; 

Result: 
1 A 
2 B 
3 C 
4 D 
5 E 
6 F 
7 w <-- problem illustrated here 

這「一DIMP,P2 P3上和P3 w「可能是w,g,G,z中的任何一個值。所以我問我如何根據其他專欄優先考慮孩子選擇?

+0

DBMS這是什麼道理呢? – 2011-04-01 21:45:59

回答

3

你想做的而不是一個連接是一個子查詢。類似這樣的:

UPDATE 
    a 
SET 
    a.val = ISNULL((
     SELECT TOP 1 x.dval 
     FROM @exdat x 
     WHERE x.id = a.id 
     ORDER BY x.magic_field -- <- here's how you specify precedence 
    ), 'ReasonableDefault') 
FROM 
    @test a 
+0

做到了,謝謝! – zdux 2011-04-01 22:07:06

1

嘗試在您的更新中使用CROSS APPLY。由@ extdat.dimp值低於訂單的例子:

DECLARE @test TABLE 
(
    id int, 
    val char(1) 
); 
DECLARE @exdat TABLE 
(
    id int, 
    dval char(1), 
    dimp char(2) 
); 
INSERT INTO @test (id,val) 
      SELECT 1,'a' 
    UNION ALL SELECT 2,'b' 
    UNION ALL SELECT 3,'c' 
    UNION ALL SELECT 4,'d' 
    UNION ALL SELECT 5,'e' 
    UNION ALL SELECT 6,'f' 
    UNION ALL SELECT 7,'g' 
; 
INSERT INTO @exdat (id,dval,dimp) 
      SELECT 1,'A','p1' 
    UNION ALL SELECT 2,'B','p3' 
    UNION ALL SELECT 3,'C','p1' 
    UNION ALL SELECT 4,'D','p2' 
    UNION ALL SELECT 5,'E','p2' 
    UNION ALL SELECT 6,'F','p3' 
    UNION ALL SELECT 7,'w','p2' 
    UNION ALL SELECT 7,'g','p3' 
    UNION ALL SELECT 7,'G','p1' 
    UNION ALL SELECT 7,'z','p4' 
; 
UPDATE @test 
SET 
    t.val = e.dval 
FROM @test as t 
CROSS APPLY 
(
    SELECT TOP(1) * FROM @exdat as cae 
    WHERE t.id = cae.id 
    ORDER BY cae.dimp 
) as e 

; 
SELECT * FROM @test; 

如果使用這種方法,您的結果是這樣的:

Result: 
1 A 
2 B 
3 C 
4 D 
5 E 
6 F 
7 G 

您可以通過在你的十字架改變順序修改此申請

1

我認爲使用ranking functions可以在這裏很好地使用。

在本示例中,我使用DENSE_RANK通過ORDER BY dimp選擇最高的dimp值,然後查找一個排名爲1的人。

WITH cte 
    AS (SELECT Dense_rank() OVER (PARTITION BY id ORDER BY dimp) AS foo, 
       * 
     FROM @exdat) 
UPDATE @test 
SET val = e.dval 
FROM @test t 
     INNER JOIN cte e 
     ON t.id = e.id 
WHERE foo = 1; 
1
UPDATE @test 
    SET t.val = e.dval 
FROM @test t 
    JOIN @exdat e 
    ON t.id = e.id 
    JOIN 
    (SELECT id 
      , MIN(dimp) AS dimp  --orders by dimp ascending 
     FROM @exdat 
     WHERE dval = UPPER(dval)  --keeps only rows with capital letters in dval 
     GROUP BY id 
    ) AS g 
    ON e.id = g.id 
    AND e.dimp = g.dimp