2015-06-11 39 views
0

我需要解決的問題是將數據從具有許多動態字段的表傳輸到其他結構化鍵值表中。 第一個表來自另一個系統的數據導出,並具有以下結構(它可以具有任何列名稱和數據): [UserID],[FirstName],[LastName],[Email],[您是如何日期],[你想收到每週通訊],[確認你是18+] ...將動態表列轉移到鍵值行中

第二張表是我要放的數據,它有以下結構: [UserID uniqueidentifier],[QuestionText nvarchar(500)],[問題答案nvarchar(max)]

我看到了很多例子,說明如何轉換表,但我的問題是,我不知道表1將具有什麼列。我可以以某種方式動態地轉移第一個表,因此無論它具有哪個列,它都會轉換爲鍵值結構並將數據導入到第二個表中。

我真的很感謝你對此的幫助。

+0

請發佈一些示例數據和預期的結果。 –

回答

0

在不知道列的情況下,您無法在一個查詢中實現透視或未透視。

假設你有權限,你可以做什麼,查詢sys.columns來獲取你的源表的字段名,然後動態地建立一個unpivot查詢。

--Source table 
create table MyTable (
    id int, 
    Field1 nvarchar(10), 
    Field2 nvarchar(10), 
    Field3 nvarchar(10) 
); 

insert into MyTable (id, Field1, Field2, Field3) values (1, 'aaa', 'bbb', 'ccc'); 
insert into MyTable (id, Field1, Field2, Field3) values (2, 'eee', 'fff', 'ggg'); 
insert into MyTable (id, Field1, Field2, Field3) values (3, 'hhh', 'iii', 'jjj'); 

--key/value table 
create table MyValuesTable (
    id int, 
    [field] sysname, 
    [value] nvarchar(10) 
); 



declare @columnString nvarchar(max) 

--This recursive CTE examines the source table's columns excluding 
--the 'id' column explicitly and builds a string of column names 
--like so: '[Field1], [Field2], [Field3]'. 

;with columnNames as (
    select column_id, name 
    from sys.columns 
    where object_id = object_id('MyTable','U') 
    and name <> 'id' 
), 
columnString (id, string) as (
    select 
    2, cast('' as nvarchar(max)) 
    union all 
    select 
    b.id + 1, b.string + case when b.string = '' then '' else ', ' end + '[' + a.name + ']' 
    from 
    columnNames a 
    join columnString b on b.id = a.column_id 
) 
select top 1 @columnString = string from columnString order by id desc 

--Now I build a query around the column names which unpivots the source and inserts into the key/value table. 
declare @sql nvarchar(max) 
set @sql = ' 
insert MyValuestable 
select id, field, value 
from 
    (select * from MyTable) b 
unpivot 
    (value for field in (' + @columnString + ')) as unpvt' 

--Query's ready to run. 
exec (@sql) 

select * from MyValuesTable 

如果你從一個存儲過程中讓你的源數據,則可以使用OPENROWSET的數據放在一個表,然後檢查表的列名。此鏈接顯示如何做那部分。 https://stackoverflow.com/a/1228165/300242

最後提示:如果您使用臨時表,請記住,你從tempdb.sys.columns獲得列名像這樣:

select column_id, name 
from tempdb.sys.columns 
where object_id = object_id('tempdb..#MyTable','U') 
+0

非常感謝@JC。這對我來說工作得很好。我非常感謝你的幫助。 –