Оператор обновления TSQL с помощью Join - PullRequest
4 голосов
/ 02 апреля 2011

У меня есть две таблицы с отношениями родитель / ребенок.Я хочу обновить родителя с данными от ребенка.Однако, если предположить, что есть 2 дочерних элемента, я бы хотел выбрать, какой дочерний элемент используется для обновления, в зависимости от некоторого другого столбца дочернего элемента.Вот что у меня есть: Parent: @test Child: @exdat Ожидаемый результат, результат parent после обновления должен содержать только заглавные буквы.Я хочу обновить родителя некоторыми данными от ребенка, но если их больше, я бы предпочел выбрать ребенка с dimp с 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 ]

3 голосов
/ 02 апреля 2011

То, что вы хотите сделать вместо объединения, это подзапрос. Примерно так:

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 голос
/ 02 апреля 2011
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
1 голос
/ 02 апреля 2011

Я думаю, что с помощью функций ранжирования можно найти здесь хорошее применение.

В этом примере я использовал DENSE_RANK, чтобы выбрать наибольшее значение dimp с помощью ORDER BY dimp, а затем искалодин имел ранг одного.

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 голос
/ 02 апреля 2011

Попытка использовать 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...