具有总字段的交叉点的SQL计数

时间:2017-06-17 19:49:34

标签: mysql sql-server

例如,我们在数据库中有 ServiceRequests 源表:

| Id | ClientDepartment | ServiceType | DateTimeServiced |
|----|------------------|-------------|------------------|
| 1  | Sales            | Networking  | 15.01.17         |
| 2  | Development      | Networking  | 14.02.17         |
| 3  | Development      | Networking  | 09.04.17         |
| 4  | Sales            | Software    | 11.03.17         |
| 5  | Sales            | Hardware    | 30.03.17         |
| 6  | Development      | Hardware    | 15.04.17         |

需要进行SQL select查询并获得结果:

|Client\Service| Networking | Software | Hardware | Total |
|--------------|------------|----------|----------|-------|
| Sales        | 1          | 1        | 1        | 3     |
| Development  | 2          | 0        | 1        | 3     |

其中数字是 ServiceType ClientDepartment (每个部门的服务)之间的交叉点数。

尝试这样的事情会导致非常错误结果:

select ClientDepartment,
    (select count(t1.ClientDepartment)
        from ServiceRequests t1
        where t1.ServiceType = 'Networking' 
    ) as Networking,
    (select count(t1.ClientDepartment)
        from ServiceRequests t1
        where t1.ServiceType = 'Software'
    ) as Software,
    (select count(t1.ClientDepartment)
        from ServiceRequests t1
        where t1.ServiceType = 'Hardware' 
    ) as Hardware,
    (select count(t1.ClientDepartment)
        from ServiceRequests t1
    ) as Total
from ServiceRequests
group by ClientDepartment

|Client\Service| Networking | Software | Hardware | Total |
|--------------|------------|----------|----------|-------|
| Sales        | 3          | 1        | 2        | 6     |
| Development  | 3          | 1        | 2        | 6     |

Hope for help, create example table code

2 个答案:

答案 0 :(得分:2)

您可以在案例时使用和,并按组分组 通过这种方式,您无需为每个计数进行子选择

  select 
        ClientDepartment
      , sum(case when ServiceType = 'Networking' then 1 else 0 end )as Networking
      , sum(case when ServiceType = 'Software' then 1 else 0 end ) as Software
      , sum(case when ServiceType = 'Hardware' then 1 else 0 end ) as Hardware
      , sum(case when ServiceType = 'Networking' then 1 else 0 end ) +
        sum(case when ServiceType = 'Software' then 1 else 0 end ) +
        sum(case when ServiceType = 'Hardware' then 1 else 0 end ) as  Total 
  from ServiceRequests
  group by ClientDepartment

这应该适用于DB ..

答案 1 :(得分:1)

我们可以使用Dynamic Sql实现所需的结果

GROUP BY

输出

IF OBJECT_ID('Tempdb..#Temp') IS NOT NULL
DROP TABLE #Temp
;With cte( Id , ClientDepartment , ServiceType , DateTimeServiced )
AS
(
SELECT  1  , 'Sales'            , 'Networking'  , '15.01.17' Union all         
SELECT  2  , 'Development'      , 'Networking'  , '14.02.17' Union all         
SELECT  3  , 'Development'      , 'Networking'  , '09.04.17' Union all         
SELECT  4  , 'Sales'            , 'Software'    , '11.03.17' Union all         
SELECT  5  , 'Sales'            , 'Hardware'    , '30.03.17' Union all         
SELECT  6  , 'Development'      , 'Hardware'    , '15.04.17' 
)
SELECT  ClientDepartment,
        ServiceType,
        COUNT(ServiceType)OVER(Partition by ClientDepartment,ServiceType Order by Id) AS Cnt INTO #Temp FROM cte   --Sample data created  here

DECLARE @Column1 nvarchar(max),
        @Sql nvarchar(max),
        @Column2 nvarchar(max)   

SELECT @Column1=STUFF((SELECT DISTINCT ', '+ 'ISNULL('+ServiceType +',''0'') AS '+ServiceType FROM #Temp
FOR XML PATH ('')),1,1,'')

SELECT @Column2=STUFF((SELECT DISTINCT ', '+ +QUOTENAME(ServiceType)  FROM #Temp
FOR XML PATH ('')),1,1,'')

 SET @Sql='
        SELECT *,'+REPLACE(@Column2,',','+')+' AS  Total FROM 
        (
         SELECT ClientDepartment AS ''Client\Service'','+@Column1 +'  FROM
            (    
                SELECT * FROm #Temp
            )AS SRc
        PIVOT
            (
            MAX(Cnt) FOR ServiceType IN ('+@Column2+')
            )AS PVT
            )DT
            Order by 1 desc
        '

PRINT @Sql
EXEC(@Sql)