如何将行转换为列-复杂的枢轴

时间:2019-03-05 19:24:16

标签: sql sql-server dynamic-sql

如何构建使用动态SQL返回以下列的数据集。

联名,联名地址,CFO 1名称,CFO 1电子邮件,CFO 1电话,CFO 2名称,CFO 2电子邮件,CFO 2电话,...主任1名称,主任1电子邮件,主任1电话...到5,总裁1的姓名,等等。排成一排。

我的数据库中有四个表:

联系方式:

X18_Digit_Contact_ID__c     |    Name          |    Email    |     Phone     |   Federation_ID
------------------------------------------------------------------------------------------
1                           |    John Smith    | x9@gmail.com |  546-5464889 |     1
2                           |    David smith   | x8@gmail.com |  145-5464889 |     1
3                           |    Ellen Smith   | x9@gmail.com |  546-5464889 |     1
4                           |    Dan smith     | x8@gmail.com |  145-5464889 |     1
5                           |    Kelly Smith   | x9@gmail.com |  546-5464889 |     2
6                           |    Dori smith    | x8@gmail.com |  145-5464889 |     2
7                           |    Nir Smith     | x9@gmail.com |  546-5464889 |     2
8                           |    Victor smith  | x8@gmail.com |  145-5464889 |     2

隶属关系:

X18_Digit_Contact_ID__c     |    npe5__Role__c      
-----------------------------------------------
4                           |    President                  
8                           |    President 

联盟:

Federation_ID   |  Name    |   Address
---------------------------------------
1               |   x      |   123 hello 
2               |   y      |   345 world

选区:

X18_Digit_Contact_ID__c     |    Constituency       
-----------------------------------------------
1                           |    CFO                
2                           |    CFO            
3                           |    Director               
7                           |    Director 
5                           |    Director               
6                           |    Director 

联盟1的预期结果:

  Name    |   Address   |    CFO 1        | CFO 1 Email  | CFO 1 Phone  | CFO 2        | CFO 2 Email  | CFO 2 Phone  | Director 1  | Director 1 Email | Director 1 Phone | President 1 | President 1 Email | President 1 Phone| 
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   x      |   123 hello |    John Smith   | x9@gmail.com | 546-5464889  | David smith  | x8@gmail.com | 145-5464889  | Ellen Smith | x9@gmail.com     | 546-5464889      | Dan smith   | x8@gmail.com      | 145-5464889

每个联盟可以有多个具有相同选区和隶属关系的联系人。

例如,联盟“ x”可以有一个以上的CFO和一个以上的主管。这些信息来自选区表。 (这些数字是动态的。)

然后,同一个联盟最多可以有一位主席,而该信息来自关联表。

这是我的开始方式,但并没有完全按照我的期望进行。

DECLARE @query VARCHAR(MAX)

DECLARE @pickedConstituenciesByUser varchar(MAX) = 'Chief Financial Officers,President,Executive Directors'
DECLARE @constituencies VARCHAR(MAX)
SELECT  @constituencies = STUFF (
                            (   
                                SELECT DISTINCT '],[' + Constituency__c

                                FROM    Constituency 

                                WHERE   Active__c = 1 AND Constituency__c IN (SELECT Value FROM fnc_Split_IDs(@pickedConstituenciesByUser, ','))

                                ORDER BY '],[' + Constituency__c

                                FOR XML PATH('')
                            ), 1, 2, ''
                          ) + ']'

--return 
SET @query =  
    'SELECT * FROM ' +
    '( ' +
        'SELECT  c.Name, ' +                                            
                'f.Community, ' +
                'f.CitySize, '+
                'f.CommunityCode, ' +                               
                'f.BillingStreet, ' +
                'f.BillingCity, ' +
                'f.BillingState, ' +
                'f.BillingPostalCode, ' +
                'f.BillingCountry, ' +          
                'ct.Constituency__c ' +             

        'FROM Federation f ' +

        'JOIN Contact c ON f.Account_ID = c.AccountId ' +

        'JOIN Affiliation a ON  c.X18_Digit_Contact_ID__c = a.npe5__Contact__c  ' + 
                                'AND ' +
                                'a.Affiliation_Type__c IN (''Professional'',''Lay'') ' +                                                                

        'JOIN Constituency ct ON ct.Contact__c = c.X18_Digit_Contact_ID__c AND ct.Active__c = 1 ' +         

    ') AS t ' +     

    'PIVOT (MAX(t.Name) ' + 
           'FOR t.Constituency__c IN ('+ @constituencies +')) AS pvt ' +    

    'Order BY CitySize, Community ' 

EXECUTE (@query)

此代码仅返回一名CFO和一名董事,而没有总裁。

2 个答案:

答案 0 :(得分:2)

这个评论太长了。当我们寻找消耗性数据时,帮助您使用它的人应该很容易。这是应该发布此信息的方式,以便其他人可以对其进行查询。

create table Contact
(
    X18_Digit_Contact_ID__c int
    , Name varchar(50)
    , Email varchar(50)
    , Phone varchar(15)
    , Federation_ID int
)

insert Contact values
(1, 'John Smith', 'x9@gmail.com', '546-5464889', 1)
, (2, 'David smith', 'x8@gmail.com', '145-5464889', 1)
, (3, 'Ellen Smith', 'x9@gmail.com', '546-5464889', 1)
, (4, 'Dan smith', 'x8@gmail.com', '145-5464889', 1)
, (5, 'Kelly Smith', 'x9@gmail.com', '546-5464889', 2)
, (6, 'Dori smith', 'x8@gmail.com', '145-5464889', 2)
, (7, 'Nir Smith', 'x9@gmail.com', '546-5464889', 2)
, (8, 'Victor smith', 'x8@gmail.com', '145-5464889', 2)

create table Affiliation
(
    X18_Digit_Contact_ID__c int
    , npe5__Role__c varchar(20)
)

insert Affiliation values
(4, 'President')                 
, (8, 'President')

create table Federation
(
    Federation_ID int
    , Name varchar(10)
    , Address varchar(20)
)

insert Federation values
(1, 'x', '123 hello')
, (2, 'y', '345 world')

create table Constituency
(
    X18_Digit_Contact_ID__c int
    , Constituency varchar(10)
)

insert Constituency values
(1, 'CFO')
, (2, 'CFO')
, (3, 'Director')
, (7, 'Director')
, (5, 'Director')
, (6, 'Director')

今天我没有更多时间为您提供帮助。也许其他人也可以使用我创建的数据来提供帮助。

答案 1 :(得分:0)

谢谢你们的帮助。

整整一天后,我想出了一些对我有用的东西。这可能不是解决此问题的最佳方法,但它确实有效。

希望这可以帮助其他人。

    DECLARE @pickedConstituenciesByUser varchar(8000) = 'Chief Financial Officers,Executive Directors,President'
    DECLARE @query VARCHAR(8000)    
    DECLARE @column_headers VARCHAR(8000)

    -- Creating the main temp table
    CREATE TABLE #Main_Tbl
    (   
        [ID]                varchar(50),
        column_value        varchar(255),                                           
        Community           varchar(255),
        CitySize            varchar(255),
        CommunityCode       varchar(255),           
        BillingStreet       varchar(255),
        BillingCity         varchar(255),
        BillingState        varchar(255),
        BillingPostalCode   varchar(255),
        BillingCountry      varchar(255),
        Title               varchar(255),
        RowNum              int,
        Column_header       varchar(255)
    )

    -- Inserting intital data with constituencies and (contact names into column_value)
    INSERT INTO #Main_Tbl
    SELECT  c.X18_Digit_Contact_ID__c,
            c.[Name] column_value,                                          
            f.Community,
            f.CitySize,
            f.CommunityCode,                                
            f.BillingStreet, 
            f.BillingCity, 
            f.BillingState, 
            f.BillingPostalCode, 
            f.BillingCountry, 
            ct.Constituency__c,
            0 Rownum,
            '' [Column_header]

    FROM Federation f

    JOIN Contact c ON f.Account_ID = c.AccountId                                                        

    JOIN Constituency ct ON ct.Contact__c = c.X18_Digit_Contact_ID__c AND ct.Active__c = 1 

    -- Inserting intital data with affiliations and (contact names into column_value)
    INSERT INTO #Main_Tbl
    SELECT  c.X18_Digit_Contact_ID__c,
            c.[Name] column_value,                                          
            f.Community,
            f.CitySize,
            f.CommunityCode,                                
            f.BillingStreet, 
            f.BillingCity, 
            f.BillingState, 
            f.BillingPostalCode, 
            f.BillingCountry, 
            a.npe5__Role__c,
            0 Rownum,
            '' [Column_header]          

    FROM Federation f

    JOIN Contact c ON f.Account_ID = c.AccountId

    JOIN Affiliation a ON   c.X18_Digit_Contact_ID__c = a.npe5__Contact__c 
                            AND 
                            a.Affiliation_Type__c IN ('Professional','Lay') 
                            AND 
                            a.npe5__Status__c = 'Current'                                                                                                                       

    -- Updating data with row number and column headers.
    UPDATE A
    SET A.RowNum = Z.RowNum, A.Column_header = z.Column_header
    FROM #Main_Tbl A
    JOIN
    (
            SELECT  x.ID,               
                    x.CommunityCode,
                    x.Community,
                    x.CitySize,
                    x.column_value,
                    x.Title,
                    ROW_NUMBER() OVER(PARTITION BY x.CommunityCode, x.Title ORDER BY x.column_value) RowNum,                
                    x.Title + ' ' + cast(ROW_NUMBER() OVER(PARTITION BY x.CommunityCode, x.Title ORDER BY x.column_value) as varchar(10)) Column_header                 

            FROM #Main_Tbl x

            JOIN Contact c ON x.ID = c.X18_Digit_Contact_ID__c

            WHERE Title IN (SELECT Value FROM fnc_Split_IDs(@pickedConstituenciesByUser, ','))

    ) Z ON A.ID = Z.ID

    -- Inserting the same data - but this time replacing name with email into column_value 
    INSERT INTO #Main_Tbl
    SELECT  c.X18_Digit_Contact_ID__c,
            c.Email column_value,                                           
            x.Community,
            x.CitySize,
            x.CommunityCode,                                
            x.BillingStreet, 
            x.BillingCity, 
            x.BillingState, 
            x.BillingPostalCode, 
            x.BillingCountry, 
            x.Title,
            0 Rownum,
            x.Column_header + ' Email' [Column_header]

    FROM #Main_Tbl x

    JOIN Contact c ON x.ID = c.X18_Digit_Contact_ID__c 

    -- Inserting the same data again - but this time replacing email with phone into column_value 
    INSERT INTO #Main_Tbl
    SELECT  c.X18_Digit_Contact_ID__c,
            c.Phone column_value,                                           
            x.Community,
            x.CitySize,
            x.CommunityCode,                                
            x.BillingStreet, 
            x.BillingCity, 
            x.BillingState, 
            x.BillingPostalCode, 
            x.BillingCountry, 
            x.Title,
            0 Rownum,
            x.Column_header + ' ' + 'Phone' [Column_header]

    FROM #Main_Tbl x

    JOIN Contact c ON x.ID = c.X18_Digit_Contact_ID__c

    WHERE Column_header NOT LIKE ('%Email%')

    -- Inserting the same data again - but this time replacing phone with title into column_value 
    INSERT INTO #Main_Tbl
    SELECT  c.X18_Digit_Contact_ID__c,
            a.npe5__Role__c column_value,                                           
            x.Community,
            x.CitySize,
            x.CommunityCode,                                
            x.BillingStreet, 
            x.BillingCity, 
            x.BillingState, 
            x.BillingPostalCode, 
            x.BillingCountry, 
            x.Title,
            0 Rownum,
            x.Column_header + ' ' + 'Title' [Column_header]

    FROM #Main_Tbl x

    JOIN Contact c ON x.ID = c.X18_Digit_Contact_ID__c

    JOIN Affiliation a ON x.ID = a.npe5__Contact__c AND a.npe5__Status__c = 'Current' AND a.npe5__Role__c <> 'Constituent'

    WHERE Column_header NOT LIKE ('%Email%') AND Column_header NOT LIKE ('%Phone%')

    -- creating a string with the proper column headers
    SELECT  @column_headers = STUFF 
                              (
                                (   
                                    SELECT DISTINCT '],[' + TRIM([Column_header])

                                    FROM    #Main_Tbl                                                                                                                                                                                                                                                           

                                    ORDER BY '],[' + TRIM([Column_header])

                                    FOR XML PATH('')
                                ), 1, 2, ''
                              ) + ']'

    -- replacing empty headers
    SET @column_headers = Replace(@column_headers, '[],', '')

    -- replacing email
    SET @column_headers = Replace(@column_headers, '[Email],', '')

    -- replacing phone
    SET @column_headers = Replace(@column_headers, '[Phone],', '')

    -- replacing title
    SET @column_headers = Replace(@column_headers, ',[Title]', '')

    -- Build main query 
    SET @query = 
        'SELECT * FROM ' +
        '( ' +

                'SELECT       Community
                            , CitySize
                            , CommunityCode
                            , BillingStreet
                            , BillingCity
                            , BillingState
                            , BillingPostalCode
                            , BillingCountry
                            , column_value                      
                            , Column_header

                 FROM #Main_Tbl ' +

        ') AS t ' +         

        'PIVOT (MAX(column_value) FOR Column_header IN ('+ @column_headers +')) AS pvt ' +

        'ORDER BY CitySize, Community' 

    -- Execute query
    EXECUTE (@query)

    DROP TABLE #Main_Tbl
相关问题