2011-04-01 94 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