7

私は問題があります。

T1、、テーブルがありT2ます。T_Join

T_Join:最初の列:(ID一意)例:10、11、12、13。2番目の列:CODE、の列名と同じ属性が含まれていますT2。例:タイプ、ソース、セクション、重要度。これらは、ので識別されIDますT1。これによると、属性「ソース」のIDは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など。

2番目の列はからのIDですT_Join。この例では、4つのIDが1に属することができdata_ID、これらは宣言します。その値は3番目の列(VALUE)に表示されます。

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に格納されているこのIDによって識別され、第4レベルの重要度を持つ実際のオブジェクトです。

今、私はテーブルT2を持っています。最初の列は、T1と同じdata_IDです。この表では、これらは一意です。他の列:(なんと驚くべきことでしょう!)タイプ、ソース、セクション、重要性。(実際には、4つの属性だけでなく、少なくとも50の属性があります!)したがって、テーブルは次のようになります。

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

T2には新しいデータが含まれています。これらで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になりました。これは、T1ではIDが13であり、T_Joinテーブルの属性「importance」などを参照しているためです。このようにすべてのデータを更新したいと思います。私は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

しかし、それは機能しません、エラーメッセージ:

メッセージ116、レベル16、状態1、行16サブクエリがEXISTSで導入されていない場合、選択リストで指定できる式は1つだけです。

CURSORステートメントと宣言された変数(アドバイスに基づいて)でそれを解決しようとしましたが、どちらも機能しません。

誰かが私がこれを(最も簡単な方法で)どのように解決できるか考えているなら、できるだけ詳細に答えてください。

4

1 に答える 1

5

現在の設計の問題は、正規化されたテーブルと非正規化されたテーブルが1つあり、更新を実行する必要があることです。

まず、テーブルを非正規化するT2必要があります。これにより、列が取得され、行に変換されます。SQL Server 2005+では、UNPIVOTこれを実行する関数が導入されました。

最初のステップは、行SELECTからのデータT2T_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 FiddlewithDemoを参照してください。これにより、列データが取得され、行に変換されて結果が得られます。

| 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 FiddlewithDemoを参照してください。

あなたが持っているとあなたが言った次の問題は、あなたがアンピボットする必要がある約50の列があるということです。その場合は、動的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 ('+@colsUnpivot+')
         ) unpiv
       ) u
         on j.code = u.col
     ) t
       on t1.data_id = t.data_id
       and t1.id = t.id;'

exec(@query);

SQL FiddlewithDemoを参照してください。

コードが更新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 |
于 2013-02-13T11:21:30.460 に答える