2012-10-17 90 views
2

我有水平臺(表1),我需要它將它轉變成(表2)水平數據轉換成垂直

表1:

CEO  SALESMAN PRODUCT(1) PRODUCT(2) PRODUCT(3) PRODUCT(4) PRODUCT(5) ... PRODUCT(N) 
------ ---------- ---------- ---------- ---------- ---------- ----------  ---------- 
MIKE ANDERSON 76787,00 19388,00 0,00  2723,00  217,00   6581,00 
JOHN ANGELA  0,00  0,00  73088,00 0,00  0,00   0,00 
JACK JEFF  24716,00 0,00  2995,00  0,00  0,00   0,00 
STUART MICHAEL  0,00  23338,00 42656,00 0,00  0,00   0,00 

表2:

CEO  SALESMAN PRODUCTS VALUE 
------- ----------- ---------- -------- 
MIKE ANDERSON PRODUCT(1) 76787,00 
JOHN ANGELA  PRODUCT(1) 0,00 
JACK JEFF  PRODUCT(1) 24716,00 
STUART MICHAEL  PRODUCT(1) 0,00 
MIKE ANDERSON PRODUCT(2) 19388,00 
JOHN ANGELA  PRODUCT(2) 0,00 
JACK JEFF  PRODUCT(2) 0,00 
STUART MICHAEL  PRODUCT(2) 23338,00 
MIKE ANDERSON PRODUCT(3) 0,00 
JOHN ANGELA  PRODUCT(3) 73088,00 
JACK JEFF  PRODUCT(3) 2995,00 
STUART MICHAEL  PRODUCT(3) 42656,00 
MIKE ANDERSON PRODUCT(4) 2723,00 
JOHN ANGELA  PRODUCT(4) 0,00 
JACK JEFF  PRODUCT(4) 0,00 
STUART MICHAEL  PRODUCT(4) 0,00 
MIKE ANDERSON PRODUCT(5) 217,00 
JOHN ANGELA  PRODUCT(5) 0,00 
JACK JEFF  PRODUCT(5) 0,00 
STUART MICHAEL  PRODUCT(5) 0,00 
MIKE ANDERSON ...  ... 
JOHN ANGELA  ...  ... 
JACK JEFF  ...  ... 
STUART MICHAEL  ...  ... 
MIKE ANDERSON PRODUCT(N) 6581,00 
JOHN ANGELA  PRODUCT(N) 0,00 
JACK JEFF  PRODUCT(N) 0,00 
STUART MICHAEL  PRODUCT(N) 0,00 

我到目前爲止所嘗試的是將BULK INSERT Table1放入一個臨時表中,然後處理這些數據,直到我得到我想要。問題是PRODUCT()列中的N是可變的,所以我不能創建一個包含固定列的臨時表,我需要一個動態查詢,以某種方式讀取產品列的數量並使用它。

BULK INSERT

BULK INSERT #temp 
FROM '\\path\file.csv' 
WITH 
(
FIRSTROW = 1, 
FIELDTERMINATOR= ';', 
ROWTERMINATOR = '\n', 
CODEPAGE='RAW' 
); 

臨時表:

CREATE TABLE #temp(
col1 varchar(100) null, 
col2 varchar(100) null, 
col3 varchar(100) null, 
col4 varchar(100) null, 
col5 varchar(100) null, 
... 
col397 varchar(100) null, 
col398 varchar(100) null, 
col399 varchar(100) null, 
col400 varchar(100) null 
) 

當我運行BULK INSERT我得到這個錯誤:

Msg 4832, Level 16, State 1, Line 1 
Bulk load: An unexpected end of file was encountered in the data file. 
Msg 7399, Level 16, State 1, Line 1 
The OLE DB provider "BULK" for linked server "(null)" reported an error. The provider did not give any information about the error. 
Msg 7330, Level 16, State 2, Line 1 
Cannot fetch a row from OLE DB provider "BULK" for linked server "(null)". 

這是因爲我創造一個溫度具有固定400列的文件表,並且有127個產品列。

我試圖避免像這些東西:

DECLARE @NUM_ROWS INT 

SET  @NUM_ROWS = 123 

IF @NUM_ROWS = 1 
BEGIN 
CREATE TABLE #temp(
col1 varchar(100) null 
) 
END 

IF @NUM_ROWS = 2 
BEGIN 
CREATE TABLE #temp(
col1 varchar(100) null, 
col2 varchar(100) null, 
) 
END 

... 

IF @NUM_ROWS = 400 
BEGIN 
CREATE TABLE #temp(
col1 varchar(100) null, 
col2 varchar(100) null, 
... 
col4 varchar(100) null, 
) 
END 

BULK INSERT #temp 
FROM '\\path\file.csv' 
WITH 
(
FIRSTROW = 1, 
FIELDTERMINATOR= ';', 
ROWTERMINATOR = '\n', 
CODEPAGE='RAW' 
); 

@NUM_ROWS將列數我將創建臨時表。

有誰知道一種方式,我可以將這個.csv文件動態導入到SQL Server中?動態地,我的意思是創建一個臨時表與我批量插入的產品列的數量。或者避免我上面發佈的錯誤的解決方法。

+0

你能做到在加載之前對csv文件進行任何手動操作?還是這個過程需要100%自動化? – PowerUser

+0

當然,我可以在之前操作.csv文件。其實,之前操縱它會更好。我已經搜索過操縱它,並且在粘貼值時發現了轉置,但它沒有幫助。 – Turque

+0

這是一次性任務,還是需要重複? – podiluska

回答

1

這裏有一個稍微手動方法:

  1. 開放與Excel
  2. .csv文件400個名添加到第一行。它們當然不一定是字段的名稱。只是佔位符。這樣,當您重新保存文件時,該文件將有400列。(我把這種手工方法,但你可以用VBA腳本自動化此)

從這裏開始,它的所有SQL:

  1. 採用標準的批量插入,導入到一個臨時表這有400列。
  2. 將您的數據轉化爲表2使用類似:
Insert into Table2 
Select CEO, Salesmen, 1 as ProductNum, [Product(1)] from Table1 where [Product(1)] is not null 
union 
Select CEO, Salesmen, 2 as ProductNum, [Product(2)] from Table1 where [Product(2)] is not null 
... 
union 
Select CEO, Salesmen, 400 as ProductNum, [Product(400)] from Table1 where [Product(400)] is not null 

當然,400線,這將是醜陋的,但你可以輕鬆地閱讀它,並從1數到400。

+0

這是一個簡單的好主意,這樣我就可以使用一個固定的400列臨時表,並可用於任何文件。我後面所要做的就是從臨時表中刪除「TOP 1」。 – Turque

+0

由於產品名稱不會每次都是相同的,所以我將不得不以其他方式執行SQL部分。產品列不會超過200列,因此我將保留200列來放置產品說明並執行如下操作:首先,我插入一個帶ID的列,然後更新#temp SET column204 = select column4其中ID = 2,UPDATE #temp SET column205 = select column5 where ID = 2,UPDATE #temp SET column206 = select column6 where ID = 2 ...等等,這樣我就會知道column4與column205,5到205,6到206,等最後我會做你的建議。 – Turque

+0

'插入到表2 選擇CEO,推銷員,column4爲product_value,column204作爲PRODUCT_DESCRIPTION從#TEMP 工會 選擇CEO,推銷員,column5,從#TEMP ... 工會 選擇CEO,推銷員,column200,column400 column205 from#temp' – Turque

1

如果您將CSV打開到Excel中,然後再次將其另存爲CSV,則會將其格式化爲具有固定數量的列。

您可以創建臨時表,一個循環和動態SQL

declare @sql nvarchar(max), @numcols int = 8 

select @sql = '' 
declare @i int = 1 

select @sql = @sql + ', c' + convert(varchar(5), number) + ' varchar(10) ' 
from master..spt_values 
where type='p' and number between 1 and @numcols 

select @sql = 'create table ##temp (' + substring(@sql, 3, len(@sql)) + ')' 
select @sql 

exec sp_executeSQl @sql 

BULK INSERT ##temp 
FROM '\\path\file.csv' 
WITH 
( 
FIRSTROW = 1, 
FIELDTERMINATOR= ';', 
ROWTERMINATOR = '\n', 
CODEPAGE='RAW' 
); 

從那裏,你只是套用Unpivot表中的列轉換爲行。

+0

運行上面的代碼時,出現以下錯誤: '(1 row(s)affected) Msg 208,Level 16,State 82,Line 15 無效的對象名稱'#temp'。'關於使用Unpivot,I必須「選擇」一列產品的靜態列表,由於產品可能會有所不同,因此無法提供幫助。 – Turque

+0

我的錯。在temp之前應該有兩個##。如果你的產品不同,那麼你將需要通過動態sql來構建unpivot。 – podiluska