Mysql 从另一个查询的结果向查询中添加列
好吧,我会尽可能简单地解释这一点 我有一个名为approval_Level的表,其中有两列:Mysql 从另一个查询的结果向查询中添加列,mysql,sql,sql-server,Mysql,Sql,Sql Server,好吧,我会尽可能简单地解释这一点 我有一个名为approval_Level的表,其中有两列: |LEVEL_ID |NAME | |1 |app_level_1 | |2 |app_level_2 | |3 |app_level_3 | |REQUEST_ID |PRODUCT_NAME |MANUFACTURER | |1 |wd-40 |Acme
|LEVEL_ID |NAME |
|1 |app_level_1 |
|2 |app_level_2 |
|3 |app_level_3 |
|REQUEST_ID |PRODUCT_NAME |MANUFACTURER |
|1 |wd-40 |Acme |
|2 |Windex |Acme |
|3 |Propane |Acme |
我有第二个名为requests的表,其中有3列:
|LEVEL_ID |NAME |
|1 |app_level_1 |
|2 |app_level_2 |
|3 |app_level_3 |
|REQUEST_ID |PRODUCT_NAME |MANUFACTURER |
|1 |wd-40 |Acme |
|2 |Windex |Acme |
|3 |Propane |Acme |
我有第三个表,它链接了两个名为request\u approvals的表,该表有两列:request\u ID、LEVEL\u 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_level表(即app_level_4)添加了另一个值,则需要向该表添加另一列,以动态调用app_level_4
现在,我到底该怎么做这样的事???我都不知道从哪里开始找
谢谢你的帮助 如果您使用的是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
正如菲利普所说,最好的方法是一个透视表 您可以通过如下操作选择透视表的列
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表时,它只会添加它,这里有sql server标记,所以您可以尝试下面的查询 我使用u提供的数据示例(可能字段名不同,请检查表名) 带枢轴:
-- 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
*/
带连接(左连接):
-- 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
mysql还是sqlserver?哪一个。你想用其他三个的东西创建一个新表吗?或者你只是想通过查询三个表来获得这样的结果?如果不编写一些程序来处理查询结果,你就无法实现这一点(为app_level_4添加一个新列)。