2013-02-13 13 views
7

Ho un problema.in base ai nomi delle colonne

Ho T1, T2, T_Join tabelle.

T_Join: prima colonna: ID (unico), ad esempio: 10,11,12,13. Seconda colonna: CODE, contiene attributi uguali ai nomi di colonna di T2. Es .: tipo, fonte, sezione, importanza. Questi sono identificati dallo ID nel T1. Secondo questo, l'ID di attributo 'sorgente' è 11.

ID CODE 
10 type 
11 source 
12 section 
13 importance 

Nella tavola T1, la prima colonna è il data_ID non riservate: 1020, 1020, 1020, 1022, 1022, 1022, 1023, 1023, 1028, 1028, 1028, 1035, 1035, ecc.

La seconda colonna è ID da T_Join. In questo esempio 4 ID può appartenere a 1 data_ID, questi dichiarano, di cui valore appare nella terza colonna (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 

...

Significa l'articolo con 1020 ID è di tipo 1 , proviene dalla fonte n. 123, l'oggetto reale identificato da questo ID memorizzato nella sezione 9 e ha un'importanza di 4 ° livello.

Ora ho una tabella T2. La prima colonna è la stessa data_ID di T1. In questa tabella questi sono unici. Le altre colonne: (che sorpresa!) Tipo, fonte, sezione, importanza. (In realtà, non ci sono solo quattro attributi, ma almeno cinquanta!) Quindi la tabella è qualcosa di simile:

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 

Il T2 contiene i dati più recenti. Vorrei aggiornare la colonna T1.VALUE con questi. In seguito i miei esempi di cui sopra, La versione aggiornata di T1 dovrebbe essere simile a questo:

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 
... 

Così, a data_ID 1020, l'importanza è stato di 4 e si è rivolto a 2 perché nel T1 l'ID è 13 e si riferisce ad attribuire 'importanza 'dalla tabella T_Join e così via. Vorrei aggiornare tutti i dati in questo modo. Io non sono un esperto di SQL e sono riuscito a creare questo codice:

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 

ma non funziona, il messaggio di errore:

Msg 116, livello 16, stato 1 , Linea 16 È possibile specificare solo un'espressione nell'elenco di selezione quando la sottoquery non viene introdotta con EXISTS.

ho cercato di risolverlo con la dichiarazione del cursore e dichiarato variabili (in base a un consiglio), ma non funziona neanche.

Per favore, se qualcuno ha un'idea di come potrei risolvere questo (nel modo più semplice), rispondi nel modo più dettagliato possibile.

+0

+1 È incluso un sacco di dettagli sul problema che si stanno avendo e anche mostrato quello che si è tentato di risolvere il problema. Questo è un buon primo post. – Taryn

risposta

5

Il problema con il progetto corrente è che una tabella è normalizzata e una che è de-normalizzata ed è necessario eseguire un aggiornamento.

Per prima cosa, è necessario desalizzare la tabella T2, che prenderà le colonne e la convertirà in righe. In SQL Server 2005+ è stata introdotta la funzione UNPIVOT che eseguirà ciò per te.

Il primo passaggio è per i dati da T2 e T_Join in righe. La dichiarazione è 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 

Vedi SQL Fiddle with Demo. Questo richiede i dati di colonna e lo converte in file dando il risultato:

| 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 | 

Una volta che i dati sono in quel formato, si può utilizzare in un UPDATE dichiarazione:

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; 

Vedere SQL Fiddle with Demo.

Il prossimo problema che hai dichiarato di avere è che ci sono circa 50 colonne di cui hai bisogno per unpivot. In tal caso, è possibile utilizzare SQL dinamico per ottenere l'elenco di colonne da trasformare in righe. È script SQL dinamico sarà:

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); 

Vedi SQL Fiddle with Demo.

Il codice aggiornerà T1 con il seguente risultato:

| 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

Grazie per la risposta, lo controllerò presto! – A117

Problemi correlati