Question

i have 3 table PhoneBook, DynamicField, PhoneBook_DynamicField_Rel

PhoneBook :

|---ID----|---Name----|  
    1         Reza  
    2         Ali      

DynamicField :

|---ID----|--Caption--|  
    1          Job  
    2          Level  

PhoneBook_DynamicField_Rel:

|---ID----|--PhoneBookID--|--DynamicFieldID--|---Value---|  
    1            1                 1              Emp  
    2            1                 2               1  
    3            2                 1             SomeJob    

i want execute query with this result :

|--PhoneBookID--|--Name--|--Job--|--Level--|  
        1          Reza     Emp       1  
        2          Ali    SomeJob    NULL  
Was it helpful?

Solution

Maybe something like this:

Test data:

CREATE TABLE #PhoneBook(ID INT,Name VARCHAR(100))
INSERT INTO #PhoneBook VALUES(1,'Reza'),(2,'Ali')

CREATE TABLE #DynamicField(ID INT,Caption VARCHAR(100))
INSERT INTO #DynamicField VALUES(1,'Job'),(2,'Level')

CREATE TABLE #PhoneBook_DynamicField_Rel(ID INT,PhoneBookID INT,
                                         DynamicFieldID INT,Value VARCHAR(100))
INSERT INTO #PhoneBook_DynamicField_Rel
VALUES(1,1,1,'Emp'),(2,1,2,'1'),(3,2,1,'SomeJob')

Getting the colums

DECLARE @cols VARCHAR(MAX)
SELECT @cols=STUFF
(
    (
        SELECT 
            ',' +QUOTENAME(tbl.Caption)
        FROM
            #DynamicField AS tbl
        FOR XML PATH('')
    )
,1,1,'')

Then the query like this:

DECLARE @query NVARCHAR(4000)=
N'SELECT
    *
FROM
(
    SELECT
        *
    FROM
    (
        SELECT
            PhoneBook.ID,
            PhoneBook.Name,
            field.Caption,
            rel.Value
        FROM
            #PhoneBook AS PhoneBook
            JOIN #PhoneBook_DynamicField_Rel AS rel
                ON PhoneBook.ID = rel.PhoneBookID
            JOIN #DynamicField AS field
                ON rel.DynamicFieldID=field.ID
    ) AS SourceTable
) AS p
PIVOT
(
    MAX(Value) FOR Caption IN('+@cols+')
) AS pvt'
EXECUTE(@query)

Then in my case I will drop the temp tables:

DROP TABLE #PhoneBook
DROP TABLE #DynamicField
DROP TABLE #PhoneBook_DynamicField_Rel

OTHER TIPS

What you need is dynamic pivot:

declare @collist nvarchar(max)
SET @collist = stuff((select distinct ',' + QUOTENAME(caption) 
            FROM DynamicField 
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

declare @q nvarchar(max)
set @q = '
select PhoneBookID, Name, ' + @collist + ' 
from (
    select PhoneBookID, Name, Caption, Value
        from (
        select PhoneBookID, Name, Caption, Value
        from PhoneBook pb
        inner join PhoneBook_DynamicField_Rel pbdf on pb.ID = pbdf.PhoneBookID
        inner join DynamicField df on df.ID = pbdf.DynamicFieldID
    ) as x
) as source
pivot (
    max(Value)
    for caption in (' + @collist + ')
) as pvt
'

exec (@q)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top