好吧,我会尽可能简单地解释一下。
我有一个名为approval_levels的表,其中我有两列:
|LEVEL_ID |NAME |
|1 |app_level_1 |
|2 |app_level_2 |
|3 |app_level_3 |
我有一个名为requests的第二个表,其中我有3列:
|REQUEST_ID |PRODUCT_NAME |MANUFACTURER |
|1 |wd-40 |Acme |
|2 |Windex |Acme |
|3 |Propane |Acme |
我有第三个表链接两个名为request_approvals的表,它有2列:REQUEST_ID,LEVEL_ID。当请求被批准用于特定级别时,我会在此表中插入一个值。因此,例如,假设请求1已经被批准用于所有3个级别,请求2已被批准仅用于级别1,而请求3已被批准用于级别3,该表格将显示类似这样的内容。
|REQUEST_ID |LEVEL_ID |
|1 |1 |
|1 |2 |
|1 |3 |
|2 |1 |
|3 |3 |
好的,接下来是挑战:我需要在报告中显示所有请求,为每个级别创建一个列,并显示该请求是否已获得该级别的批准。最终结果必须是这样的:
|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 |
请记住,如果另一个值添加到approval_levels表(即app_level_4),我需要动态地向表调用app_level_4添加另一列。
现在,我在世界上如何做这样的事情?我甚至不知道从哪里开始看?
感谢您的帮助!
答案 0 :(得分:3)
如果您正在使用SQL Server,请查看PIVOT命令。我自己写了其中一个,所以我修改它以适应你的表结构:
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
答案 1 :(得分:0)
正如菲利普所说,最好的方式是数据透视表。
您可以通过执行类似的操作来选择数据透视表的列
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
这将创建一个字符串,用于将名称括在括号[]中,以后可以在旋转表格时调用
QUERY STUFF
PIVOT
(
Some aggregate function(column value)
FOR [Name] IN (' + @Cols + ')
) as P
我知道我离开了很多,但我想我会分享如何动态构建列名,这样当你在approval_levels表中添加一个新行时它就会添加它
答案 2 :(得分:0)
这里有sql server标签,所以你可以尝试下面的查询 我使用你提供的数据示例(可能是字段名称不同,并检查表名称)
使用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
加入(左连接):
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
*/
结果:
-- 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