Sql 不存在的组项目类别计数为零
我需要找到过去五天内三种产品的清单,以及按日期分组的数量。为此,我使用了下面的TSQLSql 不存在的组项目类别计数为零,sql,sql-server,tsql,group-by,Sql,Sql Server,Tsql,Group By,我需要找到过去五天内三种产品的清单,以及按日期分组的数量。为此,我使用了下面的TSQL SELECT CONVERT(VARCHAR(10),WM_data,103) as Date, Product = CASE WHEN WM_Product = 1 THEN 'Product A' WHEN WM_Product = 2 THEN 'Product B'
SELECT CONVERT(VARCHAR(10),WM_data,103) as Date,
Product = CASE
WHEN WM_Product = 1 THEN 'Product A'
WHEN WM_Product = 2 THEN 'Product B'
ELSE 'Product C'
END,
WM_qtd as Quantity
FROM Tb_InfoProduct
GROUP BY CONVERT(VARCHAR(10),WM_data,103), WM_Product
HAVING CONVERT(VARCHAR(10),WM_data,103) > convert(VARCHAR(10),dateadd(dd, -5, getdate()),103)
ORDER BY CONVERT(VARCHAR(10),WM_data,103), WM_Product
因此,我收到:
Date Product Quantity
-------------------------------------------------
16/02/2012 Product A 132
16/02/2012 Product C 10
17/02/2012 Product A 163
17/02/2012 Product B 61
17/02/2012 Product C 58
18/02/2012 Product A 7
18/02/2012 Product B 2
但我需要:
Date Product Quantity
-------------------------------------------------
16/02/2012 Product A 132
16/02/2012 Product B 0 -- This
16/02/2012 Product C 10
17/02/2012 Product A 163
17/02/2012 Product B 61
17/02/2012 Product C 58
18/02/2012 Product A 7
18/02/2012 Product B 2
18/02/2012 Product C 0 -- This
如何实现这一点?首先,您的查询存在一些问题:
SELECT
子句包含的列既不在groupby
中,也不在聚合的–WM\u qtd
中。你的意思是求和,不是吗CONVERT(103)
格式化的日期无法进行有意义的比较或排序。我建议您要么使用不同的格式(如112
),要么使用不同的方法删除时间部分,然后再应用格式(仅在SELECT
子句中,或者根本不在SQL中)HAVING
子句过滤源数据集,这是低效的,因为所有数据都必须被提取、分组,然后才进行过滤。在这种特殊情况下,最好使用WHERE
子句过滤数据Tb\u InfoProduct
,并按日期和产品分组以获取数字–与您在查询中已经做的相同,只有您的分组依据
和选择
子句将引用的日期和产品列必须是相应派生列表中的列,而不是Tb\u InfoProduct
表中的列
出于回答的目的,我假设您请求的Tb\u InfoProduct
子集包含输出中必须存在的所有日期和所有产品,因此,要获得这两个列表,我只需从Tb\u InfoProduct
子集中选择不同的日期和不同的产品。这是一个完整的近似解决方案:
SELECT
Date = CONVERT(VARCHAR(10), d.Date, 103),
Product = CASE p.WM_Product
WHEN 1 THEN 'Product A'
WHEN 2 THEN 'Product B'
ELSE 'Product C'
END,
Quantity = SUM(WM_qtd)
FROM (
SELECT DISTINCT Date = DATEADD(DAY, DATEDIFF(DAY, 0, WM_data), 0)
FROM Tb_InfoProduct
WHERE WM_data >= DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()) - 4, 0)
) d
CROSS JOIN (
SELECT DISTINCT WM_Product
FROM Tb_InfoProduct
WHERE WM_data >= DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()) - 4, 0)
) p
LEFT JOIN (
SELECT
Date = DATEADD(DAY, DATEDIFF(DAY, 0, WM_data), 0),
WM_Product
FROM Tb_InfoProduct
WHERE WM_data >= DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()) - 4, 0)
) i ON d.Date = i.Date AND p.WM_Product = i.WM_Product
GROUP BY
d.Date,
p.WM_Product
ORDER BY
d.Date,
p.WM_Product
如果请求的子集可能会忽略您希望包含在输出中的某些日期和/或产品,则应以不同的方式构建列表。例如,您可以使用Products
引用表作为产品列表,当然,如果您有一个产品列表的话。至于日期,您可能需要按照@OMG Ponies的建议为给定范围生成日期列表(这个问题可能会帮助您:)。如果使用sql 2008:
SELECT table1.date, table2.productid, isnull(table3.total,0) total FROM
--get the last 5 days
(
select distinct date from mytable1 where date > getdate() - 5
) table1
--get the 3 products
CROSS JOIN
(
select productid from product where productid in (1,2,3)
) table2
OUTER APPLY (SELECT SUM(1) Total from YourTable
where yourtable.date = table1.date
and yourtable.productid = table2.productid) Table3
您需要有(或生成)一个日期列表,然后在日期值上与之外部连接。另外,您应该在
WHERE
子句中进行筛选(使用日期对象而不是字符串)