带Join的TSQL Update语句

时间:2011-04-01 21:26:24

标签: sql tsql join sql-update

我有两个父/子关系表。我想用来自孩子的数据更新父母。但假设有2个孩子,我希望能够根据孩子的其他一些栏目选择使用哪个孩子进行更新。 这是我到目前为止: 家长:@test 孩子:@exdat 预期结果,更新后父母的结果应仅包含大写字母。我想用来自孩子的一些数据来更新父母,但是如果存在多个数据,我宁愿选择一个p1比p2高,p2高于p3而p3高于p4的孩子

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 

这个“w”可以是任何值w,g,G,z。所以我问我如何根据其他专栏确定子选择的优先顺序?

4 个答案:

答案 0 :(得分: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

答案 1 :(得分: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

您可以通过更改CROSS APPLY

中的顺序来修改此项

答案 2 :(得分: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; 

答案 3 :(得分: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