Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQL Merge duplicate records to one row

I have a SQL Server 2016 database with a couple thousand records in.

The records are displayed currently like so;

enter image description here

And i would like to have this outcome;

enter image description here

I will then export the data to Excel.

Essentially there are multiple contact details for one person and multiple account types, instead of each detail taking up a new row, I need to collapse them all onto one single row with added columns, I can create a new db that has the columns inserted if needed.

I have tried variation of these solutions;

By Taryn

By Hassan - I couldn't figure out what i needed to join and where.

By Brad C - I had some success with this in the fact it truncated the tables in this db.

And a few others but the links have gotten buried, I'm sorry.

Schema

CREATE TABLE [dbo].[Contacts] 
(
    [emplid] [float] NULL,
    [emcoid] [float] NULL,
    [name] [varchar](50) NULL,
    [conttp] [varchar](50) NULL,
    [phone] [varchar](50) NULL,
    [fax] [varchar](50) NULL,
    [email] [varchar](50) NULL,
    [auth] [float] NULL,
    [ainits] [varchar](50) NULL,
    [adate] [datetime] NULL,
    [atime] [datetime] NULL,
    [uinits] [varchar](50) NULL,
    [udate] [datetime] NULL,
    [utime] [datetime] NULL
) ON [PRIMARY]
GO

Test Data

INSERT [dbo].[Contacts_NEW] ([emplid], [emcoid], [name], [conttp], [phone], [fax], [email], [auth], [ainits], [adate], [atime], [uinits], [udate], [utime]) 
VALUES (100, 103, N'MR Bert Ernie', N'PENS', N'1800100300', NULL, N'[email protected]', 1, N'MK785487', CAST(N'2016-08-17T00:00:00.000' AS DateTime), CAST(N'2068-02-07T00:00:00.000' AS DateTime), N'MK785487', CAST(N'2016-08-17T00:00:00.000' AS DateTime), CAST(N'2068-02-07T00:00:00.000' AS DateTime))
INSERT [dbo].[Contacts_NEW] ([emplid], [emcoid], [name], [conttp], [phone], [fax], [email], [auth], [ainits], [adate], [atime], [uinits], [udate], [utime]) 
VALUES (100, 104, N'MR Bert Ernie', N'OFFI', N'1800100300', NULL, N'[email protected]', 1, N'MK785487', CAST(N'2016-08-17T00:00:00.000' AS DateTime), CAST(N'2068-02-07T00:00:00.000' AS DateTime), N'MK785487', CAST(N'2016-08-17T00:00:00.000' AS DateTime), CAST(N'2068-02-07T00:00:00.000' AS DateTime))
INSERT [dbo].[Contacts_NEW] ([emplid], [emcoid], [name], [conttp], [phone], [fax], [email], [auth], [ainits], [adate], [atime], [uinits], [udate], [utime])    
VALUES (100, 105, N'MR Bert Ernie', N'CONT', N'1800100300', NULL, N'[email protected]', 1, N'MK785487', CAST(N'2016-08-17T00:00:00.000' AS DateTime), CAST(N'2068-02-07T00:00:00.000' AS DateTime), N'MK785487', CAST(N'2016-08-17T00:00:00.000' AS DateTime), CAST(N'2068-02-07T00:00:00.000' AS DateTime))
INSERT [dbo].[Contacts_NEW] ([emplid], [emcoid], [name], [conttp], [phone], [fax], [email], [auth], [ainits], [adate], [atime], [uinits], [udate], [utime]) 
VALUES (200, 113, N'Roger Federer', N'PENS', N'78415784156', NULL, N'[email protected]', 1, N'MK785477', CAST(N'2016-08-17T00:00:00.000' AS DateTime), CAST(N'2068-02-07T00:00:00.000' AS DateTime), N'MK785477', CAST(N'2016-08-17T00:00:00.000' AS DateTime), CAST(N'2068-02-07T00:00:00.000' AS DateTime))
INSERT [dbo].[Contacts_NEW] ([emplid], [emcoid], [name], [conttp], [phone], [fax], [email], [auth], [ainits], [adate], [atime], [uinits], [udate], [utime]) 
VALUES (200, 114, N'Roger Federer', N'OFFI', N'78415784157', NULL, N'[email protected]', 1, N'MK785477', CAST(N'2016-08-17T00:00:00.000' AS DateTime), CAST(N'2068-02-07T00:00:00.000' AS DateTime), N'MK785477', CAST(N'2016-08-17T00:00:00.000' AS DateTime), CAST(N'2068-02-07T00:00:00.000' AS DateTime))

Given more time I may be able to figure it out, but as it stands I am stumped. And I don't fancy exporting this into excel and manipulating all the records by hand.

Any help would be appreciated, or a point in the right direction.

Thank you.

like image 243
Lloyd Avatar asked Jul 13 '18 13:07

Lloyd


People also ask

How do I combine duplicate rows into one in SQL?

To combine, use GROUP_CONCAT() function to combine some attributes in two rows into one. As a separator, use hyphens.

How do I merge data from multiple duplicate rows into one?

There are three steps to group your duplicates with Merge Duplicates Wizard: Select the table. Choose any columns that will be checked for duplicate entries. Indicate columns with the values to merge, set delimiters, and click on the Finish button.

How do I concatenate multiple rows into a single row in SQL Server?

You can concatenate rows into single string using COALESCE method. This COALESCE method can be used in SQL Server version 2008 and higher. All you have to do is, declare a varchar variable and inside the coalesce, concat the variable with comma and the column, then assign the COALESCE to the variable.


1 Answers

Conditional aggregation can handle this fairly easily. The challenging piece is those emails but not impossible at all. However, in your sample output there are only 17 columns (emcoid 1 - 4). Easy enough if you need to adjust this to accommodate a fifth.

select x.emplid
    , x.name
    , conttp = max(case when x.RowNum = 1 then x.conttp end)
    , conttp2 = max(case when x.RowNum = 2 then x.conttp end)
    , conttp3 = max(case when x.RowNum = 3 then x.conttp end)
    , conttp4 = max(case when x.RowNum = 4 then x.conttp end)
    , conttp5 = max(case when x.RowNum = 5 then x.conttp end)
    , conttp6 = max(case when x.RowNum = 6 then x.conttp end)
    , phone = max(case when x.RowNum = 1 then x.phone end)
    , phone2 = max(case when x.RowNum = 2 then x.phone end)
    , x.fax
    , email = max(case when x.RowNum = 1 then emails.email end)
    , email2 = max(case when x.RowNum = 2 then emails.email end)
    , emcoid1 = max(case when x.RowNum = 1 then x.emcoid end)
    , emcoid2 = max(case when x.RowNum = 2 then x.emcoid end)
    , emcoid3 = max(case when x.RowNum = 3 then x.emcoid end)
    , emcoid4 = max(case when x.RowNum = 4 then x.emcoid end)
from 
(
    select *
        , RowNum = ROW_NUMBER() over(partition by emplid order by emcoid)
    from Contacts c
) x
join
(
    select *
        , RowNum = ROW_NUMBER() over(partition by emplid order by (select null))
    from
    (
        select distinct email
            , emplid
        from Contacts
    ) a
) emails on emails.RowNum = x.RowNum
            and emails.emplid = x.emplid
group by x.emplid
    , x.name
    , x.fax
like image 59
Sean Lange Avatar answered Oct 16 '22 17:10

Sean Lange