2

水平テーブル(Table1)があり、それを(Table2)に変換するために必要です

表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

これまでに試したのは、Table1を一時テーブルにBULK INSERTしてから、必要なデータが得られるまでこのデータを処理することです。問題は、PRODUCT()列のNが可変であるため、固定列の一時テーブルを作成できず、製品列の数量を読み取って処理できる動的クエリが必要なことです。

バルクインサート

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ファイルをSQLServerに動的にインポートする方法を知っている人はいますか?動的とは、一括挿入するPRODUCTSの列数を使用して一時テーブルを作成することを意味します。または、上記で投稿したエラーを回避するための回避策。

4

2 に答える 2

1

これはやや手動のアプローチです:

  1. Excel で .csv ファイルを開く
  2. 最初の行に 400 個の列名を追加します。もちろん、フィールドの実際の名前である必要はありません。ただのプレースホルダー。このようにして、ファイルを再保存すると、ファイルには 400 列が含まれます。(私はこれを手動アプローチと呼んでいますが、VBA スクリプトを使用してこれを自動化できます)

ここから先は、すべて SQL です。

  1. 標準の一括挿入を使用して、これを 400 列のステージング テーブルにインポートします。
  2. 次のようなものを使用して、データを table2 に挿入します。
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 まで数えることができます。

于 2012-10-18T14:16:16.197 に答える
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を適用して、テーブルを列から行に変換するだけです。

于 2012-10-17T20:45:53.877 に答える