Home > Software design >  SQL - Multiple records into one line with conditions
SQL - Multiple records into one line with conditions

Time:02-12

I have two tables that look like this

Account Table

| Account Number | Account Name   |
| -------------- | -------------- |
| 12345          | Bob Jones      |
| 12346          | Jenny Smith    |
| 12347          | Mary Frederick |

Email Table

| Account Number         | Email Type    |Email                  | IsPrimary       |
| ---------------------- | --------------|-----------------------|-----------------|
| 12345                  | WORK          | [email protected]    | 0               |  
| 12345                  | HOME          | [email protected]    | 0               |
| 12345                  | WORK          | [email protected]    | 1               |
| 12345                  | HOME          | [email protected]  | 0               |
| 12346                  | HOME          | [email protected]     | 1               |
| 12346                  | WORK          | [email protected]    | 0               |
| 12346                  | HOME          | [email protected]   | 0               |
| 12347                  | HOME          | [email protected]     | 0               |

I need to end up with results like this:

| Account Number           | Account Name      | Home Email         | Work Email         | Alternate Email      |
| ------------------------ | ----------------- |--------------------|--------------------|----------------------|
| 12345                    | Bob Jones         | [email protected] | [email protected] | [email protected] |
| 12346                    | Jenny Smith       | [email protected]  | [email protected] | [email protected]  |
| 12347                    | Mary Frederick    | [email protected]  |                    |                      |

I have all possible combinations of emails such as multiple work and no home, no primaries at all, multiple primaries... etc.

I need the logic to be:

  • Home Email: When type is Home. If there is a primary, choose the first one. If there is no primary, choose the first non-primary home email. Otherwise make it blank
  • Work Email: Same as above but for work
  • Alternate Email: Any third email on the list. If there are more than 3, choose home over work.

I have tried a ton of things and nothing has worked well. Here is my top attempt -two things don't work about it. The 'top 1' returns a lot of nulls and the code for alternates isn't always mutually exclusive to the home and work email, especially for people that have no primary checked:

select distinct
A01.AccountNumber, 
A01.FirstName,
A01.LastName,
(
    select top 1 
    case
       when (A07.Active = 1 and A07.EmailType = 'HOME' and A07.UseAsPrimary = 1)
        then A07.EmailAddress
       when (A07.Active = 1 and A07.EmailType = 'HOME')
        then A07.EmailAddress
    end 
    from A07_AccountEmails AS A07 
    where A07.AccountNumber = A01.AccountNumber

) as HomeEmail
,(
    select top 1 
    case
       when (A07.Active = 1 and A07.EmailType = 'WORK'  and A07.EmailType is not null)--and A07.UseAsPrimary = 1)
        then A07.EmailAddress
       when (A07.Active = 1 and A07.EmailType = 'WORK')
        then A07.EmailAddress
    end 
    from A07_AccountEmails AS A07 
    where A07.AccountNumber = A01.AccountNumber 

) as WorkEmail
,(
    select top 1 (A07.EmailAddress)
    from A07_AccountEmails A07
    where A07.AccountNumber = A01.AccountNumber
    and A07.Active = 1 and A07.UseAsPrimary = 0
) as AlternateEmailMulti
from A01_AccountMaster A01
left outer join A07_AccountEmails A07 on A07.AccountNumber = A01.AccountNumber
where
A01.[Status] = 'A'

CodePudding user response:

It seems a simple sub-query per email address should do the trick? I have added them in an OUTER APPLY to allow the values to be used twice, once in the select, and once to be excluded from the alternate email column.

declare @Account table (Number int, [Name] varchar(64));
declare @Email table (AccountNumber int, [Type] varchar(4), Email varchar(256), IsPrimary bit);

insert into @Account (Number, [Name])
values
(12345, 'Bob Jones'),
(12346, 'Jenny Smith'),
(12347, 'Mary Frederick');

insert into @Email (AccountNumber, [Type], Email, IsPrimary)
values
(12345, 'WORK', '[email protected]', 0),
(12345, 'HOME', '[email protected]', 0),
(12345, 'WORK', '[email protected]', 1),
(12345, 'HOME', '[email protected]', 0),
(12346, 'HOME', '[email protected]', 1),
(12346, 'WORK', '[email protected]', 0),
(12346, 'HOME', '[email protected]', 0),
(12347, 'HOME', '[email protected]', 0);

select A.Number, A.[Name]
  , E.Home [Home Email]
  , E.Work [Work Email]
  , (
    select top 1 Email
    from @Email
    where AccountNumber = A.Number
    and Email not in (E.Home, E.Work)
    order by case when [Type] = 'HOME' then 1 else 0 end desc
  )
from @Account A
outer apply (
  select 
    (select top 1 Email from @Email where AccountNumber = A.Number and [Type] = 'HOME' order by IsPrimary desc),
    (select top 1 Email from @Email where AccountNumber = A.Number and [Type] = 'WORK' order by IsPrimary desc)
) E (Home, Work);

Returns your desired results:

Account Number Account Name Home Email Work Email Alternate Email
12345 Bob Jones [email protected] [email protected] [email protected]
12346 Jenny Smith [email protected] [email protected] [email protected]
12347 Mary Frederick [email protected] NULL NULL

Note: If you provide your sample data as DDL DML (as I have here) it makes it much easier for people to assist.

  • Related