1

Alright, I'll try to explain this as simple a possible.

I have a table called approval_levels in which I have 2 columns:

|LEVEL_ID  |NAME          |
|1         |app_level_1   |
|2         |app_level_2   |
|3         |app_level_3   |

I have a second table called requests, in which I have 3 columns:

|REQUEST_ID    |PRODUCT_NAME    |MANUFACTURER   |
|1             |wd-40           |Acme           |
|2             |Windex          |Acme           |
|3             |Propane         |Acme           |

I have a third table which links the two called request_approvals which has 2 columns: REQUEST_ID, LEVEL_ID. When a request is approved for a specific level, I insert a value into this table. So, for example, lets say request 1 has been approved for all 3 levels, request 2 has been approved for only level 1, and request 3 has been approved for level 3, the table would show something like this.

|REQUEST_ID    |LEVEL_ID       |
|1             |1              |
|1             |2              |
|1             |3              |
|2             |1              |
|3             |3              |

Ok, so here the challenge: I need to show in a report all the requests, create a columns for each level and show whether or not that request is approved for that level. The end result has to be something like this:

|REQUEST_ID |PRODUCT_NAME |MANUFACTURER |app_level_1 |app_level_2 |app_level_3 |
|1          |wd-40        |Acme         |X           |X           |X           | 
|2          |Windex       |Acme         |X           |            |            |
|3          |Propane      |Acme         |            |            |X           | 

Keep in mind that if another value is added to the approval_levels table (ie app_level_4), I need to add another column to the table call app_level_4 dynamically.

Now, how in the world do I do something like this??? I don't even know where to start looking?

Thanks for the help!

3
  • 1
    mysql or sqlserver? which one. Commented Apr 15, 2014 at 3:21
  • are you trying to create a new table with the stuff from the other three? or are you trying to just query the three table to get results like that? Commented Apr 15, 2014 at 3:34
  • You cannot pull this off (adding a new column for app_level_4) without writing some program to process the result of a query. Commented Apr 15, 2014 at 3:46

3 Answers 3

3

If you're using SQL Server, take a look at the PIVOT command. I just wrote one of these myself, so I modified it to fit your table structure:

DECLARE @COLUMNS    NVARCHAR(MAX)
DECLARE @SQL        NVARCHAR(MAX)

SELECT @COLUMNS = COALESCE(@COLUMNS + ', ','') + QUOTENAME(NAME) FROM approval_levels

SELECT @SQL = N'
    SELECT REQUEST_ID, PRODUCT_NAME, MANUFACTURER, ' + @COLUMNS + '
    FROM (
        SELECT
            r.REQUEST_ID,
            r.PRODUCT_NAME,
            r.MANUFACTURER,
            a.NAME
        FROM
            request_approvals ra
            INNER JOIN approval_levels a ON a.LEVEL_ID = ra.LEVEL_ID
            INNER JOIN requests r ON r.REQUEST_ID = ra.REQUEST_ID
        ) p
    PIVOT(COUNT(NAME) FOR NAME IN ( ' + @COLUMNS + ' )
    ) AS pvt'

EXEC sp_executesql @SQL
Sign up to request clarification or add additional context in comments.

Comments

0

As Phillip said the best way would be a pivot table.

you can select the columns for the pivot table by doing something like so

SELECT DISTINCT NAME INTO #TEMP
FROM approval_levels

DECLARE @cols NVARCHAR(2000)
SET @cols = STUFF(( SELECT  "],[" + t.NAME 
FROM #Temp AS t
FOR XML PATH("") ), 1, 2, "") + "]"
DROP TABLE #Temp 

this will create a string for you encasing the names in brackets[] that you can then call later when you pivot the table

QUERY STUFF

PIVOT 
(
    Some aggregate function(column value)
    FOR [Name] IN (' + @Cols + ')
) as P

I know i left a lot out but thought i would at lest share how to build the column names dynamically so that when you add a new row to the approval_levels table it will just add it

Comments

0

there is sql server tag in here, so you can try below query i use the data example that u provided (probably the field name is different, and check the table name)

with Pivot:

-- pivot solution 
select pvt.request_id, pvt.product_name, pvt.manufacturer
--pivot columns
, case when pvt.[1] = 1 then 'X' else '' end as lvl1
, case when pvt.[2] = 1 then 'X' else '' end as lvl2
, case when pvt.[3] = 1 then 'X' else '' end as lvl3
--, case when pvt.[4] = 1 then 'X' else '' end as lvl4
from
(
 select a.request_id, a.product_name, a.manufacturer, b.level_id
 from @requests a
 left join @request_approval b on a.request_id=b.request_id
) aa
Pivot
(
 count(aa.level_id)
 for aa.level_id in([1],[2],[3] /*,[4]*/)
) as pvt

with Join (left join):

select tbl.request_id,tbl.product_name,tbl.manufacturer
, case when zz.applvl1 is not null then 'X' else '' end as lvl1
, case when xx.applvl2 is not null then 'X' else '' end as lvl2
, case when yy.applvl3 is not null then 'X' else '' end as lvl3
from
    @requests tbl left join
    (
    select a.request_id, a.product_name, a.manufacturer, cc.Name as applvl1
    from @requests a
    left join @request_approval b on a.request_id=b.request_id
    left join (select c.level_ID, c.name from @Approval_levels c where c.level_ID = 1) cc on b.level_id=cc.level_ID
    where b.level_id = 1
    ) as zz on tbl.request_id = zz.request_id
    left join 
    (
    select a.request_id, a.product_name, a.manufacturer, dd.Name as applvl2
    from @requests a
    left join @request_approval b on a.request_id=b.request_id
    left join (select c.level_ID, c.name from @Approval_levels c where c.level_ID = 2) dd on b.level_id=dd.level_ID
    where b.level_id = 2
    ) as xx on tbl.request_id=xx.request_id
    left join
    (
    select a.request_id, a.product_name, a.manufacturer, ee.Name as applvl3
    from @requests a
    left join @request_approval b on a.request_id=b.request_id
    left join (select c.level_ID, c.name from @Approval_levels c where c.level_ID = 3) ee on b.level_id=ee.level_ID
    where b.level_id = 3
    ) as yy on tbl.request_id=yy.request_id

    --FOR the next Level
    /*
    left join
    (
    select a.request_id, a.product_name, a.manufacturer, ee.Name as applvl4
    from @requests a
    left join @request_approval b on a.request_id=b.request_id
    left join (select c.level_ID, c.name from @Approval_levels c where c.level_ID = 3) ff on b.level_id=ff.level_ID
    where b.level_id = 4
    ) as ww on tbl.request_id=ww.request_id
    --don't forget to add ww.applv4 in the select column
    */

RESULT:

-- LEFT JOIN RESULT
request_id  product_name  manufacturer  lvl1 lvl2 lvl3
----------- ------------- ------------- ---- ---- ----
1           wd-40         Acme          X    X    X
2           Windex        Acme          X         
3           Propane       Acme                    X


-- PIVOT RESULT
request_id  product_name  manufacturer  lvl1 lvl2 lvl3
----------- ------------ -------------- --------------
1           wd-40        Acme           X    X    X
2           Windex       Acme           X         
3           Propane      Acme                     X

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.