关于sql server:T-SQL动态数据透视

T-SQL dynamic pivot

好的,我有一张像这样的桌子

1
2
3
4
5
6
7
8
9
10
ItemID | ColumnName | VALUE
1      | name       | Peter
1      | phone      | 12345678
1      | email      | peter@host.com
2      | name       | John
2      | phone      | 87654321
2      | email      | john@host.com
3      | name       | Sarah
3      | phone      | 55667788
3      | email      | sarah@host.com

现在我要把它变成:

1
2
3
4
ItemID | name  | phone    | email
1      | Peter | 12345678 | peter@host.com
2      | John  | 87654321 | john@host.com
3      | Sarah | 55667788 | sarah@host.com

我一直在研究动态透视示例,但似乎无法将它们应用到我的场景中。

有人能帮忙吗?


请看下面的示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
CREATE TABLE #Table (
        ID INT,
        ColumnName VARCHAR(250),
        VALUE VARCHAR(250)
)

INSERT INTO #Table SELECT 1,'name','Peter'
INSERT INTO #Table SELECT 1,'phone','12345678'
INSERT INTO #Table SELECT 1,'email','[email protected]'
INSERT INTO #Table SELECT 2,'name','John'
INSERT INTO #Table SELECT 2,'phone','87654321'
INSERT INTO #Table SELECT 2,'email','[email protected]'
INSERT INTO #Table SELECT 3,'name','Sarah'
INSERT INTO #Table SELECT 3,'phone','55667788'
INSERT INTO #Table SELECT 3,'email','[email protected]'

---I assumed your tablename as TESTTABLE---
DECLARE @cols NVARCHAR(2000)
DECLARE @query NVARCHAR(4000)

SELECT  @cols = STUFF(( SELECT DISTINCT TOP 100 PERCENT
                                '],[' + t.ColumnName
                        FROM    #Table AS t
                        --ORDER BY '],[' + t.ID
                        FOR XML PATH('')
                      ), 1, 2, '') + ']'

SELECT  @cols

SET @query = N'SELECT ID,'+ @cols +' FROM
(SELECT t1.ID,t1.ColumnName , t1.Value FROM #Table AS t1) p
PIVOT (MAX([Value]) FOR ColumnName IN ( '
+ @cols +' ))
AS pvt;'


EXECUTE(@query)

DROP TABLE #Table


试试这个:

SQL Server 2005+

1
2
3
4
5
6
7
8
9
10
 ;WITH
        cte_name  AS(SELECT * FROM <table> WHERE ColumnName='name'),
        cte_phone AS(SELECT * FROM <table> WHERE ColumnName='phone'),
        cte_email AS(SELECT * FROM <table> WHERE ColumnName='email')
  SELECT n.ItemID,n.Value [Name],p.Value [Phone],e.Value [Email]
  FROM  cte_name n
  JOIN  cte_phone p
  ON    n.ItemID=p.ItemID
  JOIN  cte_email e
  ON    n.ItemID=e.ItemID

SQL小提琴演示


您不需要动态透视,因为它将是一个不同的表。只需这样做:

1
2
3
4
5
name    phone   email
---------------------------------
Peter            
        123456
                 peter@host.com

检查这个SQL小提琴

1
2
3
4
5
6
7
8
9
10
11
SELECT DISTINCT u.ItemID, n.Value AS 'name', p.Value AS 'phone', e.Value AS 'email'
FROM UserData u
INNER JOIN(
SELECT ItemID, VALUE
FROM UserData WHERE ColumnName = 'name') n ON n.ItemID = u.ItemID
INNER JOIN(
SELECT ItemID, VALUE
FROM UserData WHERE ColumnName = 'phone') p ON p.ItemID = u.ItemID
INNER JOIN(
SELECT ItemID, VALUE
FROM UserData WHERE ColumnName = 'email') e ON e.ItemID = u.ItemID


以下是我用于联系人列表的查询:)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
SELECT *
FROM
    (
    SELECT Contact_Id AS CT
          , [Age]
          , [Sex]
          , [State]
          , [Country]
          , [Keyword]
          , [Married]
          , [Kids]
          , [Car]
     FROM
         (SELECT c.PropertyName
               , c.ValueString
               , c.Contact_Id
          FROM
              ContactProfiles c) AS ctp
         PIVOT (MAX(ctp.ValueString) FOR PropertyName IN ([Age], [Sex], [State], [Country], [Keyword], [Married], [Kids], [Car])) AS PivotTable
         ) AS pvt

WHERE
    pvt.[Age] > 18
    AND (pvt.[State] = 'CA' OR pvt.[State] = 'NY')
    AND pvt.[Sex] = 'F'
    --*AND pvt.[Keyword] LIKE '%B;%'
    AND pvt.[Married] = 'True'
    AND pvt.[Kids] > 0

您是否尝试过:

1
2
3
4
SELECT ItemID, name, phone, email
FROM
(SELECT [ItemID] ,[ColumnName] ,[VALUE] FROM Item) Item
PIVOT (MAX(VALUE) FOR ColumnName IN (name, phone, email) ) AS pvt