關於UNPIVOT 操作符

2021-09-08 20:12:56 字數 3952 閱讀 3280

簡而言之,unpivot操作符就是取得乙個行的資料集合,然後把每一行都轉換成多個行資料。為了更好地理解,請看下圖:

圖1從上圖中,你能發現unpovot操作符,取得了兩行資料,每行包含三個price值,然後將這些轉化成6行資料,其中每個產品**都是乙個不同的行。

unpivot 命令制定了兩個不同的列型別。第乙個型別是列中不被轉換的。在例子中,id、產品名字列是這樣的列型別。第二種列型別就是那些被轉換的。諸如productcode, wholesale 和retail 這三列。在我上面的例子中,那些沒有被轉換的列將被在每套列值集合中重複,而另外的那些列將被轉換成行。

下面就是 unpivot 的語法:

select [columns not unpivoted],

[unpivot_column],

[value_column],

from

()as unpivot ( [value_column] for [unpivot_column] in ( ) )

as

where:

: 為源資料轉換後的表確定乙個別名。

:  被轉換的列的列名稱。

: 為轉換操作的整套生產,確定乙個別名。

為了更好地理解我們看下面的例子:

簡單的例子

use tempdb;

goif object_id('phonenumbers') is not null drop table phonenumbers;

gocreate table phonenumbers (

personid int,

homephone varchar(12),

cellphone varchar(12),

workphone varchar(12),

faxnumber varchar(12));

insert into phonenumbers values

(1,null,'444-555-2931',null,null),

(2,'444-555-1950','444-555-2931',null, null),

(3,'444-555-1950', null,'444-555-1324','444-555-2310'),

(4,'444-555-1950','444-555-2931','444-555-1324',

'444-555-1987');

listing 1: 建立並填充phonenumbers 資料

select personid, phonetype, phonenumber

from (

select personid, homephone, cellphone, workphone, faxnumber

from phonenumbers ) as src

unpivot (

phonenumber for phonetype in

(homephone, cellphone, workphone, faxnumber)) as unpvt;

listing 2: 行列轉換語法例子

執行上面**後顯示如下圖:

通過這個例子,我們發現執行結果中每行資料只包含乙個單一的**號碼,同時注意到結果中在原表中有幾個號碼不為null則有幾行資料,id也就有幾次。接下來我們進一步通過使用unpivot來加深認識。

第二個例子中,我將使用兩個操作符來行轉列來轉換一套名字/值 的兩列資料。具體如下:

在表 custpref裡面 我有四對名稱和值。

我們將使用不同的unpivot操作符來建立乙個結果集,每乙個preftype的名字和值針對每個custid 和custname。併聯使用操作符的作用是為了轉換兩組列。這樣講能表示為乙個引數名稱和值在一行裡面。執行**如下:

通過這個輸出結果,能發現不同的type對應不同的值得列,並且要關聯custid。整個查詢通過兩個不同的unpovot操作符同時使用了where 子句來合併輸出結果(基於列名前五個字元相同的進行匹配),第乙個行轉列轉換的是資料,第二個為型別,where限制了比較前五個字元,我能取得匹配的資料組。

**如下:

use tempdb;

godeclare @colnames varchar(1000);

set @colnames = '';

-- get prefvalue columns

select @colnames=stuff((

select distinct ',' + quotename(column_name)

from information_schema.columns p2

where table_name = 'custpref'

and column_name like 'pref_type'

for xml path(''), type).value('.', 'varchar(max)')

,1,1,'')

-- get preftype columns

declare @colvalues varchar(1000);

set @colvalues = '';

select @colvalues=stuff((

select distinct ',' + quotename(column_name)

from information_schema.columns p2

where table_name = 'custpref'

and column_name like 'pref_data'

for xml path(''), type).value('.', 'varchar(max)')

,1,1,'')

-- generate unpivot statement

declare @cmd nvarchar(2000);

set @cmd = 'select custid, custname, preftype, prefvalue from ' +

'(select custid, custname, ' + @colnames + ',' + @colvalues +

' from custpref) as perf unpivot (prefvalue for prefvalues in (' +

@colvalues + ')) as up1 unpivot (preftype for preftypes in (' +

@colnames + ')) as up2 where ' +

'substring(prefvalues,5,1) = substring(preftypes,5,1);'

-- print unpivot command

print @cmd

-- execute unpivot command

execute sp_executesql @cmd

結果是與上面的例子完全相同的。

為了完成和這個動態的sql,我使用了information_schema.columns檢視。這個檢視能幫我們設定兩個變數@colnames和

@colvalues ,這就包含了用逗號區分的列名的字串。這兩個變數被用來構建動態的行轉列查詢。一旦我建立了動態的sql就能,執行這個sp_executesql了。

這是乙個簡單的例項,但是相同的邏輯可以應用於更多的不同的組列的轉換。

unpivot操作符在2005 首次被引入,允許我們將多個name/value 列從不規範的表中建立到乙個規範畫的結果集中,並且一一對應於選定的列。通過使用這個操作符,我們能同時轉換多個不同組的name/value 的成對的列。

關於UNPIVOT 操作符

簡而言之,unpivot操作符就是取得乙個行的資料集合,然後把每一行都轉換成多個行資料。為了更好地理解,請看下圖 圖1從上圖中,你能發現unpovot操作符,取得了兩行資料,每行包含三個price值,然後將這些轉化成6行資料,其中每個產品 都是乙個不同的行。unpivot 命令制定了兩個不同的列型別...

關於CString的 操作符

檢查自已的 時,發現乙個比較弱智的錯誤,是關於轉碼的,和cstring的 操作符有關。為了能簡單重現,我模擬了一下 未有unicode或 unicode定義 uses conversion cstring stest t test中文 stest a2w stest messageboxw null...

關於操作符的總結

其中 的兩個運算元必須為整數。左移操作符 右移操作符 左移相當於乘法 左移1位,乘2 右移相當於除法 右移1位,除2 右移運算分為邏輯移位 左邊用0填充,右邊丟棄 和算術移位 左邊用符號位填充,右邊丟棄 按位與 按位或 按位異或 位操作符的運算元必須是整數。復合賦值符 sizeof,型別 其中 有按...