简体   繁体   中英

Merge two rows that contain the same Id but different data into one row

I have a very tricky question for you all

Suppose I have the following tables

Table AccountType :

Id       Type
 1     Checking
 2      Savings 

Table Customer_Account :

Customer_Id      Account_Type_Id
    450                 1
    450                 2
    451                 1

The table Customer_Account contains a list of Customers' Ids with their Account type Ids. The Account_Type_Id is a foreign key coming from the AccountType.Id.

Suppose in the Customer_Account table, a customer named Josh (id 450) can have both a checking and a savings account as shown above. I can output this customer with his id and type of account like so by having a LEFT JOIN twice on the AccountType table:

SELECT CustAccount.Customer_Id AS Id, Account1.Type AS Account_Type_1, Account2.Type AS Account_Type_2
FROM Customer_Account CustAccount
LEFT JOIN AccountType Account1
ON Account1.Id = CustAccount.Account_Type_Id
LEFT JOIN AccountType Account2
ON Account2.Id = CustAccount.Account_Type_Id

The output will be:

 Id        Account_Type_1         Account_Type_2           
450           Checking               Checking 
450           Savings                Savings
451           Checking               Checking   

What I'm trying to do is that if a customer like Josh (id 450) has both a checking and a savings account, I want to output the two rows of data above into one row like so:

 Id        Account_Type_1      Account_Type_2
450           Checking            Savings

And also, if a customer has only one type of account (like customer with id 451 here), I want only that type of account to appear under the corresponding column like so:

 Id        Account_Type_1      Account_Type_2
451           Checking            

Or if customer with id 451 had only a Savings account the ouput should be:

Id        Account_Type_1      Account_Type_2
451                              Savings

I want 'Checking' to only appear under Accoun_Type_1 and 'Savings' under Account_Type_2. If I do a GROUP BY CustAccount.Customer_Id, I get this:

 Id        Account_Type_1      Account_Type_2
450           Checking            Checking
451           Checking            Checking

Any help from any expert will be very appreciated.

Thanks.

This looks like a straight-forward application for a FULL OUTER JOIN:

SELECT COALESCE(ac1.id, ac2.id) AS id, ac1.Account_Type_1, ac2.Account_Type_2
  FROM (SELECT c.Customer_ID AS Id, t.Type AS Account_Type_1
          FROM Customer_Account AS c
          JOIN AccountType      AS t ON c.Account_Type_ID = t.ID AND t.ID = 1) AS ac1
  FULL OUTER JOIN
       (SELECT c.Customer_ID AS Id, t.Type AS Account_Type_2
          FROM Customer_Account AS c
          JOIN AccountType      AS t ON c.Account_Type_ID = t.ID AND t.ID = 2) AS ac2
    ON ac1.Id = ac2.Id;

If your DBMS does not support FULL OUTER JOIN but does support LEFT OUTER JOIN, then you can use:

SELECT ac0.id, ac1.Account_Type_1, ac2.Account_Type_2
  FROM (SELECT DISTINCT c.Customer_ID AS Id FROM Customer_Account AS c) AS ac0
  LEFT OUTER JOIN
       (SELECT c.Customer_ID AS Id, t.Type AS Account_Type_1
          FROM Customer_Account AS c
          JOIN AccountType      AS t ON c.Account_Type_ID = t.ID AND t.ID = 1) AS ac1
    ON ac0.id = ac1.id
  LEFT OUTER JOIN
       (SELECT c.Customer_ID AS Id, t.Type AS Account_Type_2
          FROM Customer_Account AS c
          JOIN AccountType      AS t ON c.Account_Type_ID = t.ID AND t.ID = 2) AS ac2
    ON ac0.Id = ac2.Id;

The first sub-query generates the list of customer IDs that exist; the second generates the list for account type 1 (Checking); the third generates the list for account type 2 (Saving). The joins ensure that every account is properly recognized.

i think this should help you

1 : Sql Select Query Question. Merge Rows or else

this should help you

Adding more conditions to your ON clauses:

ON Account1.Id = CustAccount.Account_Type_Id and Account1.Account_Type_Id = 1

ON Account2.Id = CustAccount.Account_Type_Id and Account2.Account_Type_Id = 2

will result in output that includes the account(s) held by the customer. If they only have one account then the other account type will be NULL.

Edit: Sorry, I failed to appreciate that you don't have a table of customers. You can create a temporary table with a list of distinct Customer_Id values and use that as the first table in your JOINs.

select distinct Customer_Id into #Customers
    from Customer_Account

Or the much more straightforward:

select distinct C.Customer_Id,
    ( select 'Checking' from Customer_Account where Customer_Id = C.CustomerId and Account_type_Id = 1 ) as Account_Type_1,
    ( select 'Savings' from Customer_Account where Customer_Id = C.CustomerId and Account_type_Id = 2 ) as Account_Type_2,
    from Customer_Account as C

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