Mysql 从另一个查询的结果向查询中添加列

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

好吧,我会尽可能简单地解释这一点

我有一个名为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           |
|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添加一个新列)。