Как преобразовать строки в столбцы - сложный круг - PullRequest
0 голосов
/ 05 марта 2019

Как создать набор данных, который возвращает следующие столбцы, используя динамический 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' может иметь более одного финансового директора и более одного директора. Эта информация поступает из таблицы избирателей. (Эти числа являются динамическими.)

Тогда одна и та же федерация может иметь более одного президента, и эта информация поступает из таблицы принадлежности.

Вот как я начал, но он не совсем так, как я ожидал.

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)

Этот код возвращает только одного финансового директора и одного директора, а не президентов.

Ответы [ 2 ]

2 голосов
/ 06 марта 2019

Это слишком долго для комментария.Когда мы ищем потребляемые данные, это должно быть легко для человека, помогающего вам их использовать.Вот как эта информация должна быть опубликована, чтобы другие могли запросить ее.

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')

У меня больше нет времени, чтобы помочь вам сегодня.Может быть, кто-то еще сможет использовать данные, которые я создал, чтобы помочь.

0 голосов
/ 06 марта 2019

Спасибо, ребята, за попытку помочь.

После целого дня я смог придумать что-то, что работает для меня. Возможно, это не лучший способ справиться с этим, но он работает.

Надеюсь, это может помочь кому-то еще.

    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
...