简体   繁体   中英

SQL query to return identical rows as columns dynamically named with increment number

What I need to obtain is to return all rows as columns dynamically and in case Label value exist more than one same value to return like (eg Phone, Phone1, Phone2):

For data with isActive=1 and IsPrincipal=1 will be displayed on column without number (eg Phone, Fax, E-mail )

create table #Contacts  
(
     ContactID int, 
     LabelID int, 
     Label nvarchar(25), 
     [Value] nvarchar(25), 
     IsActive bit, 
     IsPrimary bit, 
     CustomerID int
)

insert into #Contacts  
values
    (1, 1,  'Phone', '(541) 754-3010', 1, 1, 1),
    (2, 1,  'Phone', '(541) 764-3011', 1, 1, 2),
    (3, 1,  'Phone', '(541) 754-3013', 1, 0, 2),
    (4, 1,  'Phone', '(541) 754-3014', 1, 0, 2),
    (5, 2,  'Phone personal', '1111 111 1111', 1, 1, 2),
    (6, 3,  'Fax', '+44 41 444-5555', 1, 1, 2),
    (7, 3,  'Fax', '+44 41 444-5595', 1, 0, 2),
    (8, 4,  'E-mail', 'John@sales.com', 1, 0, 1),
    (9, 4,  'E-mail', 'office@ExpertBike.com', 1, 1, 1),
    (10, 4, 'E-mail', 'Mary@purchasing.com', 1, 0, 1)


create table #Customer (CustomerID int, [Name] nvarchar(30))

insert into #Customer
values
    (1, 'Sport Playground'),
    (2, 'Expert Bike EU')

What I need to display after joining this tables is shown here:

    Customer Name       Phone            Phone1            Phone2            Phone personal      Fax                  Fax1              E-mail                    E-mail1               E-mail2
    Sport Playground    (541) 754-3010                                                                                                  office@ExpertBike.com     John@sales.com        Mary@purchasing.com
    Expert Bike EU      (541) 764-3011   (541) 754-3013    (541) 754-3014    1111 111 1111       +44 41 444-5555      +44 41 444-5595

This requirement puts me in trouble.

Something like the following should do the trick...

SET NOCOUNT ON;

IF OBJECT_ID('tempdb..#Contacts', 'U') IS NOT NULL 
DROP TABLE #Contacts;

CREATE TABLE #Contacts (
     ContactID int, 
     LabelID int, 
     Label nvarchar(25), 
     [Value] nvarchar(25), 
     IsActive bit, 
     IsPrimary bit, 
     CustomerID int
);

insert into #Contacts  
values
    (1, 1,  'Phone', '(541) 754-3010', 1, 1, 1),
    (2, 1,  'Phone', '(541) 764-3011', 1, 1, 2),
    (3, 1,  'Phone', '(541) 754-3013', 1, 0, 2),
    (4, 1,  'Phone', '(541) 754-3014', 1, 0, 2),
    (5, 2,  'Phone personal', '1111 111 1111', 1, 1, 2),
    (6, 3,  'Fax', '+44 41 444-5555', 1, 1, 2),
    (7, 3,  'Fax', '+44 41 444-5595', 1, 0, 2),
    (8, 4,  'E-mail', 'John@sales.com', 1, 0, 1),
    (9, 4,  'E-mail', 'office@ExpertBike.com', 1, 1, 1),
    (10, 4, 'E-mail', 'Mary@purchasing.com', 1, 0, 1);


IF OBJECT_ID('tempdb..#Customer', 'U') IS NOT NULL 
DROP TABLE #Customer;

CREATE TABLE #Customer (
    CustomerID int, 
    [Name] nvarchar(30)
    );

insert into #Customer
values
    (1, 'Sport Playground'),
    (2, 'Expert Bike EU');

--=======================================================
--=======================================================

IF OBJECT_ID('tempdb..#ContactLabelRN', 'U') IS NOT NULL 
DROP TABLE #ContactLabelRN;

SELECT 
    c.ContactID, c.LabelID, c.Label, c.Value, c.IsActive, c.IsPrimary, c.CustomerID,
    rn = ROW_NUMBER() OVER (PARTITION BY c.CustomerID, c.Label ORDER BY c.IsPrimary DESC, c.ContactID ASC) - 1
    INTO #ContactLabelRN
FROM
    #Contacts c
WHERE 
    c.IsActive = 1
ORDER BY
    c.ContactID;

-------------------------------------------------

DECLARE 
    @ContactLabel VARCHAR(8000) = '',
    @sql VARCHAR(8000) = '',
    @DeBug BIT = 0;

WITH 
    cte_LabelRN AS (
        SELECT DISTINCT 
            clr.LabelID,
            clr.Label,
            clr.rn
        FROM 
            #ContactLabelRN clr
        )
SELECT 
    @ContactLabel = CONCAT(@ContactLabel, ',
    [', lr.Label, NULLIF(lr.rn, 0), '] = MAX(CASE WHEN clr.Label = ''', lr.Label, ''' AND clr.rn = ', lr.rn, ' THEN clr.[Value] END)')
FROM
    cte_LabelRN lr
ORDER BY
    lr.LabelID,
    lr.rn;

SET @sql = CONCAT('
SELECT 
    [Customer Name] = c.[Name]',
    @ContactLabel, '
FROM 
    #ContactLabelRN clr
    JOIN #Customer c
        on clr.CustomerID = c.CustomerID
GROUP BY 
    c.[Name];')

IF @DeBug = 1
BEGIN 
    PRINT(@sql);
END;
ELSE
BEGIN 
    EXEC(@sql);
END;

Results...

Customer Name                  Phone                     Phone1                    Phone2                    Phone personal            Fax                       Fax1                      E-mail                    E-mail1                   E-mail2
------------------------------ ------------------------- ------------------------- ------------------------- ------------------------- ------------------------- ------------------------- ------------------------- ------------------------- -------------------------
Expert Bike EU                 (541) 764-3011            (541) 754-3013            (541) 754-3014            1111 111 1111             +44 41 444-5555           +44 41 444-5595           NULL                      NULL                      NULL
Sport Playground               (541) 754-3010            NULL                      NULL                      NULL                      NULL                      NULL                      office@ExpertBike.com     John@sales.com            Mary@purchasing.com

HTH, Jason

You can also use PIVOT

WITH t_comp AS
(SELECT t.Name,
        CASE WHEN t.IsPrimary = 0 
             THEN CONCAT(t.Label,CAST(rnum AS VARCHAR)) 
             ELSE t.Label
         END Label,
        t.Value
   FROM (SELECT cn.*, 
                cs.Name, 
                ROW_NUMBER() OVER (PARTITION BY cn.CustomerID, cn.LabelID, cn.IsPrimary ORDER BY cn.IsPrimary DESC) rnum
           FROM #Contacts cn
          INNER JOIN #Customer cs
             ON cn.CustomerID = cs.CustomerID
        ) t
)

SELECT Name,
       Phone,
       Phone1,
       Phone2,
       [Phone Personal],
       Fax,
       Fax1,
       [E-mail],
       [E-mail1],
       [E-mail2]
  FROM t_comp
 PIVOT (MAX(Value)
   FOR Label IN (Phone,
                 Phone1,
                 Phone2,
                 [Phone Personal],
                 Fax,
                 Fax1, 
                 [E-mail],
                 [E-mail1],
                 [E-mail2])) p

Result

Name                 Phone          Phone1          Phone2          Phone Personal  Fax             Fax1            E-mail                  E-mail1         E-mail2
Expert Bike EU      (541) 764-3011  (541) 754-3013  (541) 754-3014  1111 111 1111   +44 41 444-5555 +44 41 444-5595 NULL                    NULL            NULL
Sport Playground    (541) 754-3010  NULL            NULL            NULL            NULL            NULL            office@ExpertBike.com   John@sales.com  Mary@purchasing.com

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM