SQL - 修改查询以创建列

时间:2017-04-07 12:50:34

标签: sql sql-server

我目前有这个查询。过去常常符合我的要求。

 SELECT sites.sitename,
   severity.severity,
   COALESCE(Count(vulns.id), 0) AS Totals
FROM   sites
   INNER JOIN systems
           ON sites.id = systems.siteid
   CROSS JOIN severity
   LEFT JOIN vulns
          ON vulns.systemid = systems.id
             AND vulns.risk_factor = severity.severity
GROUP  BY sites.sitename,
      severity.severity 

这会返回

之类的结果
SiteName | Severity | Totals
Orlando  | Red      | 0
Orlando  | Yellow   | 1
Orlando  | Green    | 22
Orlando  | Orange   | 1321
Tampa    | Red      | 22
Tampa    | Yellow   | 111
Tampa    | Green    | 223
Tampa    | Orange   | 121

如何修改此查询以将严重性细分为列。如

SiteName | Red | Yellow | Green | Orange
Orlando  | 0   | 1      | 22    | 1321

3 个答案:

答案 0 :(得分:1)

您可以使用条件聚合

 SELECT sites.sitename,   
        Count(CASE WHEN severity.severity = 'Red' THEN vulns.id END) AS Red,
        Count(CASE WHEN severity.severity = 'Yellow' THEN vulns.id END) AS Yellow,
        Count(CASE WHEN severity.severity = 'Green' THEN vulns.id END) AS Green,
        Count(CASE WHEN severity.severity = 'Orange' THEN vulns.id END) AS Orange    
FROM   sites
   INNER JOIN systems
           ON sites.id = systems.siteid
   CROSS JOIN severity
   LEFT JOIN vulns
          ON vulns.systemid = systems.id
             AND vulns.risk_factor = severity.severity
GROUP  BY sites.sitename

注意:您不需要COALESCE,因为COUNT(NULL)无论如何都会返回0

答案 1 :(得分:1)

您在自己的表中拥有severity这一事实使其能够在没有太多开销的情况下变得动态。

使用动态条件聚合:

create table severity (severity varchar(32));
insert into severity values ('Red'),('Yellow'),('Green'),('Orange');

declare @cols nvarchar(max);
declare @sql  nvarchar(max);
select @cols = stuff((
    select distinct 
      char(10)+'      , ' 
      + quotename(se.severity)
      +' = sum(case when se.severity = '''+se.severity+''' then 1 else 0 end)'
    from severity se
    order by 1
    for xml path (''), type).value('.','nvarchar(max)')
  ,1,0,'')
select  @sql ='
select 
    si.sitename'+@cols+'
FROM   sites si
   INNER JOIN systems sy
           ON si.id = sy.siteid
   CROSS JOIN severity se
   LEFT JOIN vulns
          ON vulns.systemid = systems.id
             AND vulns.risk_factor = severity.severity
GROUP  BY si.sitename
group by Id'
select CodeGenerated = @sql
--exec(@sql);

rextester演示:http://rextester.com/TYDFP90293

生成查询:

select 
    si.sitename
  , [Green] = sum(case when se.severity = 'Green' then 1 else 0 end)
  , [Orange] = sum(case when se.severity = 'Orange' then 1 else 0 end)
  , [Red] = sum(case when se.severity = 'Red' then 1 else 0 end)
  , [Yellow] = sum(case when se.severity = 'Yellow' then 1 else 0 end)
FROM   sites si
   INNER JOIN systems sy
           ON si.id = sy.siteid
   CROSS JOIN severity se
   LEFT JOIN vulns
          ON vulns.systemid = systems.id
             AND vulns.risk_factor = severity.severity
GROUP  BY si.sitename
group by Id

答案 2 :(得分:0)

IF OBJECT_ID(N'tempdb..#temp') IS NOT NULL
    DROP TABLE #temp

;WITH cte1(SiteName , Severity , Totals)
AS
(
select 'Orlando'  , 'Red'      , 0      Union all
select 'Orlando'  , 'Yellow'   , 1      Union all
select 'Orlando'  , 'Green'    , 22     Union all
select 'Orlando'  , 'Orange'   , 1321   Union all
select 'Tampa'    , 'Red'      , 22     Union all
select 'Tampa'    , 'Yellow'   , 111    Union all
select 'Tampa'    , 'Green'    , 223    Union all
select 'Tampa'    , 'Orange'   , 121
)
SELECT *INTO #temp FROM cte1

SELECT SiteName,
       MAX(CASE WHEN Severity = 'Red' THEN Totals END) Red,
       MAX(CASE WHEN Severity = 'Yellow' THEN Totals END) Yellow,
       MAX(CASE WHEN Severity = 'Green' THEN Totals END) Green,
       MAX(CASE WHEN Severity = 'Orange' THEN Totals END) Orange

  FROM  #temp
 GROUP BY SiteName