sqljoingroup-byleft-joinconditional-aggregation

SQL table join - 1 column data split to 2 columns depending on another column


I have some data in x2 tables (d and i) that I want to join and split 1 table's data (i) in to 2 columns depending on data in another column of table i.

Example of the data I have is (I have cut out multiple fields as both tables hold a lot more data than I require):

Table: INFO

isite inum idet idata
332 1 20 001122334455
332 2 20 112233445566
332 3 20 223344556677
332 1 22 Samsung
332 2 22 Sony
332 3 22 LG

Table: DEVICE

dsite dnum dname
332 1 abc123
332 2 def456
332 3 ghi789

What I want to do is join the 2 tables and depending on the value of i.det determines which column header i.data goes in to. So my query stands as:

SELECT d.dname as Unit_name, i.idata as Unit_Data FROM DEVICE d 
LEFT JOIN INFO i 
    ON d.dsite = i.isite AND d.dnum = i.inum 
WHERE (i.idet = 20 OR i.idet = 22)
AND d.dsite = 332;

Which will give me the data listing the dname twice with each piece of data as follows:

Unit_name Unit_data
abc123 001122334455
abc123 Samsung
def456 112233445566
def456 Sony
ghi789 223344556677
ghi789 LG

My desired output though would be as follows:

Unit_name Unit_MAC Unit_Manufacturer
abc123 00112233445566 Samsung
def456 11223344556677 Sony
ghi789 22334455667788 LG

So basically when idet = 20 the idata is joined under Unit_MAC for the matching isite and inum, and when idet = 22 the idata is joined under the Unit_Manufacturer for the matching isite and inum.

Hopefully what I have put has made sense, I'm sure what I want is probably very simple but I can't wrap my head round what my query needs to be at the moment! Thanks for any pointers in advance!!


Solution

  • Use conditional aggregation in your query:

    SELECT d.dname AS Unit_name, 
           MAX(CASE WHEN i.idet = 20 THEN i.idata END) AS Unit_MAC,
           MAX(CASE WHEN i.idet = 22 THEN i.idata END) AS Unit_Manufacturer
    FROM DEVICE d LEFT JOIN INFO i 
    ON d.dsite = i.isite AND d.dnum = i.inum 
    WHERE d.dsite = 332 AND (i.idet = 20 OR i.idet = 22)
    GROUP BY d.dname;
    

    I assume that dname is unique in DEVICE.

    See the demo.