2013-02-13 7 views
7

У меня проблема.Обновление sql на основе имен столбцов

У меня есть T1, T2, T_Join столы.

T_Join: первая колонка: ID (уникальный) например .: 10,11,12,13. Второй столбец: CODE, он содержит атрибуты, равные именам столбцов T2. Например: тип, источник, раздел, важность. Они идентифицируются ID в T1. В соответствии с этим, идентификатор атрибута 'источник' является 11.

ID CODE 
10 type 
11 source 
12 section 
13 importance 

В таблице T1, первый столбец является data_ID, который не является уникальным: 1020, 1020, 1020, 1022 1022 1022 1023, 1023, 1028, 1028, 1028, 1035, 1035 и т. Д.

Вторая колонка - ID от T_Join. В этом примере 4 ID может принадлежать к 1 data_ID, они заявляют, из которых значение отображается в третьей колонке (значение):

data_ID ID VALUE 
1020  10 1 
1020  11 123 
1020  12 9 
1020  13 4 
1022  10 2 
1022  12 15 
1023  10 2 
1023  11 108 
1023  13 2 
1028  12 20 

...

Это означает, что элемент с ID 1020 Тип 1 , происходит от источника No.123, реального объекта, который идентифицируется этим идентификатором, хранящимся в разделе 9, и имеет значение 4-го уровня.

Теперь у меня есть таблица T2. Первый столбец - это тот же идентификатор данных, что и в T1. В этой таблице они уникальны. Другие столбцы: (как удивительно!) Тип, источник, раздел, важность. (На самом деле, есть не только четыре атрибута, но по крайней мере пятьдесят!) Так таблица выглядит примерно так:

data_ID type source section importance 
1020  1  123  9  2 
1022  1  95  3  5 
1023  2  108  21  4 
1028  1  147  17  5 

Т2 содержит новые данные. Я хотел бы обновить столбец T1.VALUE. После моих примеров выше, обновленный T1 должен выглядеть следующим образом:

data_ID ID VALUE 
1020  10 1 
1020  11 123 
1020  12 9 
1020  13 2 
1022  10 1 
1022  12 3 
1023  10 2 
1023  11 108 
1023  13 4 
1028  12 17 
... 

Так, в data_ID 1020, значение было 4, и оказалось на 2, так как в Т1 идентификатор 13 и относится приписывать «значение 'из таблицы T_Join и так далее. Я хотел бы обновить все данные таким образом. Я не SQL эксперт и мне удалось создать этот код:

update T1 set VALUE = 
(select * from T2 
inner join T_Join on ID= 
(SELECT 
    c.name 
FROM 
    sys.objects o 
INNER JOIN 
    sys.columns c 
ON 
    c.object_id = o.object_id 
AND o.name = 'T2') 
where T1.data_ID = T2.data_ID and T2.ID = T_Join.ID) 

from T1 
inner join T2 on T1.data_ID = T2.data_ID 
inner join T_Join on T1.ID = T_Join.ID 

select * from T1 

, но он не работает, то сообщение об ошибке:

Msg 116, уровень 16, состояние 1 , Строка 16 Только одно выражение может быть указано в списке выбора, если подзапрос не вводится с EXISTS.

Я попытался решить эту проблему с помощью инструкции CURSOR и объявленных переменных (основанный на совете), но он тоже не работает.

Пожалуйста, если у кого-то есть идея, как я мог бы решить это (самым простым способом), ответьте как можно подробнее.

+0

+1 Вы включили много подробностей о проблеме, что вы имеете, и даже показал, что вы пытались исправить. Это хороший первый пост. – Taryn

ответ

5

Проблема с вашим текущим дизайном заключается в том, что у вас есть одна нормализованная таблица, а другая - ненормированная, и вам необходимо выполнить обновление.

Прежде всего, вы хотите де-нормализовать таблицу T2, которая будет принимать столбцы и преобразовывать их в строки. В SQL Server 2005+ они представили функцию UNPIVOT, которая будет выполнять это для вас.

Первым шагом является SELECT данные от T2 и T_Join в строки. SELECT утверждение:

select j.id, 
    j.code, 
    u.data_id, 
    u.value 
from T_Join j 
inner join 
(
    select data_id, col, value 
    from T2 
    unpivot 
    (
    value 
    for col in (type, source, section, importance) 
) unpiv 
) u 
    on j.code = u.col 

См SQL Fiddle with Demo. Это берет данные столбцов и преобразует его в строки, дающие результат:

| ID |  CODE | DATA_ID | VALUE | 
------------------------------------- 
| 10 |  type | 1020 |  1 | 
| 11 |  source | 1020 | 123 | 
| 12 | section | 1020 |  9 | 
| 13 | importance | 1020 |  2 | 
| 10 |  type | 1022 |  1 | 
| 11 |  source | 1022 | 95 | 
| 12 | section | 1022 |  3 | 
| 13 | importance | 1022 |  5 | 
| 10 |  type | 1023 |  2 | 
| 11 |  source | 1023 | 108 | 
| 12 | section | 1023 | 21 | 
| 13 | importance | 1023 |  4 | 
| 10 |  type | 1028 |  1 | 
| 11 |  source | 1028 | 147 | 
| 12 | section | 1028 | 17 | 
| 13 | importance | 1028 |  5 | 

После того, как данные в этом формате, вы можете использовать его в UPDATE заявлении:

update t1 
set t1.value = t.value 
from t1 
inner join 
(
    select j.id, 
    j.code, 
    u.data_id, 
    u.value 
    from T_Join j 
    inner join 
    (
    select data_id, col, value 
    from T2 
    unpivot 
    (
     value 
     for col in (type, source, section, importance) 
    ) unpiv 
) u 
    on j.code = u.col 
) t 
    on t1.data_id = t.data_id 
    and t1.id = t.id; 

См SQL Fiddle with Demo.

Следующая проблема, о которой вы заявили, состоит в том, что существует около 50 столбцов, которые вам нужны для . Univot. Если это так, то вы можете использовать динамический SQL, чтобы получить список столбцов для преобразования в строки. Вы динамический SQL скрипт будет:

DECLARE @colsUnpivot AS NVARCHAR(MAX), 
    @query AS NVARCHAR(MAX) 

select @colsUnpivot = stuff((select ','+quotename(C.name) 
     from sys.columns as C 
     where C.object_id = object_id('T2') and 
       C.name not in ('data_ID') 
     for xml path('')), 1, 1, '') 

set @query 
    = 'update t1 
    set t1.value = t.value 
    from t1 
    inner join 
    (
     select j.id, 
     j.code, 
     u.data_id, 
     u.value 
     from T_Join j 
     inner join 
     (
     select data_id, col, value 
     from T2 
     unpivot 
     (
      value 
      for col in ('[email protected]+') 
     ) unpiv 
     ) u 
     on j.code = u.col 
    ) t 
     on t1.data_id = t.data_id 
     and t1.id = t.id;' 

exec(@query); 

См SQL Fiddle with Demo.

Код обновит T1 со следующим результатом:

| DATA_ID | ID | VALUE | 
------------------------ 
| 1020 | 10 |  1 | 
| 1020 | 11 | 123 | 
| 1020 | 12 |  9 | 
| 1020 | 13 |  2 | 
| 1022 | 10 |  1 | 
| 1022 | 12 |  3 | 
| 1023 | 10 |  2 | 
| 1023 | 11 | 108 | 
| 1023 | 13 |  4 | 
| 1028 | 12 | 17 | 
+0

Спасибо за ответ, я скоро проверю! – A117

Смежные вопросы