如果没有记录,如何在group by子句中返回零

时间:2016-04-23 21:24:46

标签: sql-server tsql group-by

我们每小时记录销售的每种产品的销售量。如果一小时内没有产品销售,则没有记录。我们正在尝试创建一个查询,告诉我们每个产品每天销售的最低数量。我们有正确的工作但我们不知道如何处理在一个或多个小时内没有记录从而使正确的结果为零的情况。从本质上讲,我们的查询永远不会返回零,因为它选择了至少有一次销售的记录中的最小数量。

请注意,所有时间戳都在每小时的开头;分和秒始终为0.

到目前为止,我们的查询如下:

SELECT activity_time
      ,min(hourly_quantity) AS daily_min_quantity
      ,product_name 
FROM (select cast(quantity_time AS date) AS quantity_time
            ,sum(hourly_quantity) AS hourly_quantity
            ,product_name 
      FROM Hourly_Sales 
      GROUP BY activity_time,product_name ) x 
group by activity_time,product_name

我认为我们需要在子查询中计算小时数,以确保有24小时,如果没有,则返回零,但我不确定如何做到这一点。

3 个答案:

答案 0 :(得分:1)

您需要一个最外面的选择,返回一个不同的产品列表和一个LEFT JOIN到您的销售数据。每个以NULL作为销售数据的产品都是销售额不存在的产品。使用ISNULLCOALESCE来解决此问题。

如果您提供关于(缺失)表格的更多详细信息(特别是产品,我可以帮助您进一步...

答案 1 :(得分:1)

另一种方法是在每个时期创建一个'结果'风格报告是使用日期&时间表(或CTE)创建一组日期时间,然后LEFT JOIN创建一个日期时间,并ISNULL应用默认值。

日期&时间表使这种事情变得简单快捷,但这是一个使用CTE和15分钟报告周期的伪TSQL版本:

DECLARE @StartDate DATETIME2 = '2016-01-01 00:00:00';
DECLARE @EndDate DATETIME2 = '2016-01-31 23:45:00';
DECLARE @Period INT = 15; 

WITH Dates AS
(
  SELECT @StartDate DatePeriod
  UNION ALL
  SELECT DATEADD(MINUTE, @Period, D.DatePeriod) Date FROM Dates D
  WHERE D.DatePeriod < @EndDate
)
SELECT D.DatePeriod
    ,ISNULL(MyColumn1, 0) MyColumn1
    --etc 
 FROM Dates D
    LEFT JOIN (
      --SELECT GOES HERE
    ) MyData ON MyData.SomeDateTime = D.DatePeriod
OPTION(MAXRECURSION 0)

答案 2 :(得分:0)

由于您在子查询中按“activity_time,product_name”进行分组,然后在“activity_time,product_name”的查询中再次进行分组(我猜你忘了将activity_time放在子查询的SELECT部分​​中)不是你从SUM和MIN聚合得到相同的结果?