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

时间:2014-04-15 03:19:44

标签: mysql sql sql-server

好吧,我会尽可能简单地解释一下。

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

现在,我在世界上如何做这样的事情?我甚至不知道从哪里开始看?

感谢您的帮助!

3 个答案:

答案 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