选择“case when”...产生分组结果...如何获取汇总数据?

Posted

技术标签:

【中文标题】选择“case when”...产生分组结果...如何获取汇总数据?【英文标题】:Select "case when"... yields grouped results... how to obtain aggregate data? 【发布时间】:2017-08-25 18:32:17 【问题描述】:

使用 SQL Server 2014 SP2 的新 SQL 用户。

我正在尝试确定如何改进特定查询的结果。

问题是当我选择带有Case When 的数据时,它需要我使用group by 来聚合数据。

我正在尝试消除此group by,但无法确定此查询的可行方法。

查询产生以下结果:

StoreID Devices playing devices FullScreenPlays PIPPlays
--------------------------------------------------------
 1296      1           0               0           0
 1296      7           7               7           0
 1296      7           7               0           7

我正在努力实现类似这样的目标:

StoreID Devices playing devices FullScreenPlays PIPPlays
--------------------------------------------------------------
  1296     8           7               7            7

我尝试了几种调用group by 的变体,也尝试了几种case when 的变体,但我似乎无法弄清楚我做错了什么......

任何见解将不胜感激!

SQL 代码在这里:

DECLARE @Location varchar(50) = '1296'

SELECT 
    Location.ExternalCode As [StoreID],
    COUNT(DISTINCT imdd.DeviceID) AS Devices,
    COUNT(DISTINCT esr.DeviceID) AS [playing devices],
    (CASE 
        WHEN (esr.EventID = 925) 
           THEN (COUNT(DISTINCT esr.DeviceID)) 
           ELSE 0 
     END) AS [FullScreenPlays],
    (CASE 
        WHEN (esr.EventID = 926) 
           THEN (COUNT(DISTINCT esr.DeviceID)) 
           ELSE 0 
     END) AS [PIPPlays]
 FROM 
     [iSenseMD].dbo.Location WITH (NOLOCK)
 INNER JOIN 
     iSenseMD.dbo.LocationAttribute la WITH (NOLOCK) ON Location.LocationID = la.LocationID
                                                     AND la.AttributeID = 7
                                                     AND la.Value = 1
LEFT JOIN 
    [iSenseMD].[dbo].Device imdd WITH (NOLOCK) ON location.LocationID = imdd.LocationID
                                               AND imdd.DeviceName NOT IN ('iX Gateway', 'A312778', 'A294874', '334873')
LEFT JOIN  
    [iSenseAnalytics].[dbo].[EventStringRollup] esr WITH (NOLOCK) ON imdd.LocationID = esr.LocationID 
                                                                  AND imdd.DeviceID = esr.DeviceID
                                                                  AND esr.IntervalID = 1
                                                                  AND esr.EventID IN (925, 926)  --all plays
                                                                  AND esr.RollupTimestamp >= dateadd(day, datediff(day, 1, GETDATE()), 0) 
                                                                  AND esr.RollupTimestamp < dateadd(day, datediff(day, 0, GETDATE()), 0)
WHERE 
    Location.IsActive = 1
    AND Location.LocationName NOT LIKE '%duplicate%'
    AND Location.ExternalCode = @Location  --this to add the declaration above as site constraint
GROUP BY 
    Location.ExternalCode, esr.EventID
ORDER BY 
    iSenseMD.dbo.Location.ExternalCode

任何见解将不胜感激!

谢谢!

【问题讨论】:

【参考方案1】:

我会将查询放在 CTE 中,然后从那里聚合它

WITH CTE_Example
AS
(    use iSenseMD
go

DECLARE @Location varchar(50) = '1296'

SELECT Location.ExternalCode As [StoreID]
,count(distinct imdd.DeviceID) as Devices
,count(distinct esr.DeviceID) as [playing devices]
,(case when (esr.EventID = 925) Then (count (distinct esr.DeviceID)) Else 0 End) As [FullScreenPlays]
,(case when (esr.EventID = 926) Then (count (distinct esr.DeviceID)) Else 0 End) As [PIPPlays]


FROM [iSenseMD].dbo.Location WITH (NOLOCK)

INNER JOIN iSenseMD.dbo.LocationAttribute la WITH (NOLOCK)
    ON Location.LocationID = la.LocationID
    AND la.AttributeID = 7
    AND la.Value = 1

left JOIN [iSenseMD].[dbo].Device imdd WITH (NOLOCK) ON location.LocationID = imdd.LocationID
    AND imdd.DeviceName NOT IN ('iX Gateway','A312778','A294874','334873')

left JOIN  [iSenseAnalytics].[dbo].[EventStringRollup] esr WITH (NOLOCK) ON imdd.LocationID = esr.LocationID and imdd.DeviceID = esr.DeviceID
    AND esr.IntervalID = 1
    AND esr.EventID IN (925, 926)  --all plays
    AND esr.RollupTimestamp >= dateadd(day,datediff(day,1,GETDATE()),0) 
    AND esr.RollupTimestamp < dateadd(day,datediff(day,0,GETDATE()),0)



WHERE Location.IsActive = 1
    AND Location.LocationName NOT LIKE '%duplicate%'
    AND Location.ExternalCode = @Location  --this to add the declaration above as site constraint

GROUP BY Location.ExternalCode
    ,esr.EventID)

--A GROUP BY might not be allowed either, I can't remember. But I think it'll be fine, let me know if there are any issues

/* ORDER BY 
    iSenseMD.dbo.Location.ExternalCode */
--I don't think an ORDER BY is allowed in a CTE so I have it commented out for now. Is it an absolute within the query?

SELECT StoreID, SUM(Devices), SUM([playing devices]), SUM(FullScreenPlays), 
SUM(PIPPlays)
FROM CTE_Example
GROUP BY StoreID

希望对您有所帮助,如果有任何错误,请告诉我!

【讨论】:

【参考方案2】:

您需要将您的 case 语句放在您的 count 聚合中。这样就可以去掉group by中的EventID

示例:

COUNT(DISTINCT 
       CASE WHEN (esr.EventID = 925) THEN esr.DeviceID
       ELSE NULL
    END) AS [FullScreenPlays]

原文:

(CASE 
    WHEN (esr.EventID = 925) 
    THEN (COUNT(DISTINCT esr.DeviceID)) 
    ELSE 0 
 END) AS [FullScreenPlays]

【讨论】:

以上是关于选择“case when”...产生分组结果...如何获取汇总数据?的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSQL 分组聚合查询中 filter 子句替换 case when

case when用法sql

存储过程里面的CASE,WHEN,THEN的用法

这两个case when end的条件语句查询结果为啥不一致

case when then else end

SQL:CASE WHEN ELSE END用法