Pramod Thakur
Pramod Thakur

Reputation: 169

Inner join based on comma separated field

I have two tables InvoiceLocations and PCInvoiceLocation with respective data.

enter image description here

i just want a output like following.

enter image description here

Please help.

Code from comments:

declare @@LocationId nvarchar(50)='1,2' 
declare @@sql nvarchar(Max) 
Declare @@Output table(Code nvarchar(10) not null) 
Set @@sql='SELECT Code FROM invoiceLocations WHERE Id IN ('+@LocationId+')' 
insert @@Output(Code) 
exec sp_executesql @sql

Upvotes: 2

Views: 2005

Answers (1)

Hadi
Hadi

Reputation: 37313

Create Testing Environment

First i used the following command to create the testing environment

CREATE TABLE InvoiceLocations (ID int,CODE varchar(3), VALUE varchar(3));
CREATE TABLE PCInvoiceLOcation (ID int,CategoryID INT, Locations varchar(50),DefaultLocationID int);


INSERT INTO InvoiceLocations(ID,CODE,VALUE)
VALUES(1,'BFC','BFC'),
(2,'BRH','BRH'),
(3,'BRP','BRP'),
(4,'BCC','BCC')

INSERT INTO PCInvoiceLOcation(ID,CategoryID,Locations,DefaultLocationID)
VALUES(1,1,'1,2',1),
(2,2,'2,3',2),
(3,3,'2,1',1),
(4,4,'4',4)

Solution

You can achieve this in 3 steps:

  1. First split the Locations field into rows
  2. Join these rows with the InvoiceLocations table to get related values
  3. Aggregate the results into on comma seperated filed

First split the Locations field into rows

;with tmp(ID,CategoryID,Locations,DefaultLocationID,  DataItem , Data) as (
        select ID,CategoryID,Locations,DefaultLocationID, 
                CAST( LEFT(Locations, CHARINDEX(',',Locations+',')-1) as varchar(5)),
                STUFF(Locations, 1, CHARINDEX(',',Locations+','), '')
        from PCInvoiceLOcation
    union all
        select ID,CategoryID,Locations,DefaultLocationID,  
                CAST(LEFT(Data, CHARINDEX(',',Data+',')-1) AS Varchar(5)),
                STUFF(Data, 1, CHARINDEX(',',Data+','), '')
        from tmp
        where Data > '')

Join these rows with the InvoiceLocations table to get related values

select tmp.ID,CategoryID,Locations,DefaultLocationID,  DataItem , InvoiceLocations.VALUE
from tmp
INNER JOIN InvoiceLocations ON tmp.DataItem = InvoiceLocations.ID

Aggregate the results into on comma seperated filed

Select ID,CategoryID,Locations,DefaultLocationID,  
            STUFF((SELECT ', ' + VALUE
                       FROM Tmp2 AS T3 
                       WHERE T3.ID = tmp2.ID 
                      FOR XML PATH('')), 1, 2, '')
    FROM tmp2 
    GROUP BY ID,CategoryID,Locations,DefaultLocationID

The Whole Query will looks like

;with tmp(ID,CategoryID,Locations,DefaultLocationID,  DataItem , Data) as (
        select ID,CategoryID,Locations,DefaultLocationID, 
                CAST( LEFT(Locations, CHARINDEX(',',Locations+',')-1) as varchar(5)),
                STUFF(Locations, 1, CHARINDEX(',',Locations+','), '')
        from PCInvoiceLOcation
    union all
        select ID,CategoryID,Locations,DefaultLocationID,  
                CAST(LEFT(Data, CHARINDEX(',',Data+',')-1) AS Varchar(5)),
                STUFF(Data, 1, CHARINDEX(',',Data+','), '')
        from tmp
        where Data > '')
    ,tmp2(ID,CategoryID,Locations,DefaultLocationID,  DataItem , VALUE) AS (
        select tmp.ID,CategoryID,Locations,DefaultLocationID,  DataItem , InvoiceLocations.VALUE
        from tmp
        INNER JOIN InvoiceLocations ON tmp.DataItem = InvoiceLocations.ID) 

        Select ID,CategoryID,Locations,DefaultLocationID,  
                STUFF((SELECT ', ' + VALUE
                           FROM Tmp2 AS T3 
                           WHERE T3.ID = tmp2.ID 
                          FOR XML PATH('')), 1, 2, '')
        FROM tmp2 
        GROUP BY ID,CategoryID,Locations,DefaultLocationID

Result:

enter image description here

SQLFiddle Demo

References

Upvotes: 2

Related Questions