我有一个select语句,它返回两列,一个日期列和一个count(value)
列。当count(value)
列没有任何记录时,我需要它返回0.目前,它只是一起跳过该日期记录。
以下是查询的基础知识。
select convert(varchar(25), DateTime, 101) as recordDate,
count(Value) as recordCount
from History
where Value < 700
group by convert(varchar(25), DateTime, 101)
以下是我得到的一些结果。
+------------+-------------+
| recordDate | recordCount |
+------------+-------------+
| 02/26/2014 | 143 |
| 02/27/2014 | 541 |
| 03/01/2014 | 21 |
| 03/02/2014 | 60 |
| 03/03/2014 | 113 |
+------------+-------------+
请注意它跳过2014年2月28日。这是因为count(value)
列没有任何可计数的内容。如何在日期为2014年2月28日的日期添加记录,recordCount
为0?
答案 0 :(得分:2)
要为缺少日期生成行,您可以将数据加入date dimension table
它看起来像这样:
select convert(varchar(25), ddt.DateField, 101) as recordDate,
count(t.Value) as recordCount
from History h
right join dbo.DateDimensionTable ddt
on ddt.DateField = convert(varchar(25), h.DateTime, 101)
where h.Value < 700
group by convert(varchar(25), h.DateTime, 101)
如果您的表使用DateTime列仅存储日期(意味着时间总是午夜),那么您可以替换此
right join dbo.DateDimensionTable ddt
on ddt.DateField = convert(varchar(25), h.DateTime, 101)
用这个
right join dbo.DateDimensionTable ddt
on ddt.DateField = h.DateTime
答案 1 :(得分:0)
您可以使用COUNT(*)
。如果没有找到任何列,它将返回零。如果需要,您也可以按值列对结果集进行分组。
答案 2 :(得分:0)
select convert(varchar(25), DateTime, 101) as recordDate,
CASE WHEN count(value) =0 THEN 0 ELSE COUNT(value) END recordCount
from History
where Value < 700
group by convert(varchar(25), DateTime, 101)
答案 3 :(得分:0)
使用group by时,它只会创建记录中存在的不同值列表。由于20140228没有记录,因此不会出现在该组中。
您最好的办法是生成一个值列表,您的案例中的日期,以及左键加入或将该表应用于您的历史记录表。
我似乎无法复制我的T-SQL,所以这里是一个哈希宾。
答案 4 :(得分:0)
最佳做法是让您拥有一个数据集市,其中日期的单独维度表与您可能感兴趣的所有日期保持一致 - 即使它们缺少金额。 DMason的答案显示了具有这种维度表的查询。
为了与最佳实践保持一致,您将拥有一个事实表,您可以将这些历史数据保存在您需要的粒度级别(每天,在本例中),因此您不需要GROUP BY除非你需要更粗糙的粒度(每周,每月,每年)。
在您的运营数据库和数据集市数据库中,日期将存储为日期,而不是......
但是,那么,既然这是现实世界,你可能无法改变其他人所做的......如果你:a)只关心[历史]中出现的日期,b)这些日期永远不会以小时/分钟存储;然后跟随查询可能是您需要的:
SELECT MyDates.DateTime, COUNT(*)-1 AS RecordCount
FROM (
SELECT DISTINCT DateTime FROM History
) MyDates
LEFT JOIN History H
ON MyDates.DateTime = H.Datetime
AND H.Value < 700
GROUP BY MyDates.DateTime
尝试在DateTime上添加索引,并使用最早/最晚的日期进一步约束查询,以获得更好的性能结果。
答案 5 :(得分:0)
我同意Dates表(AKA时间维度)是正确的解决方案,但有一个更简单的选项:
SELECT
CONVERT(VARCHAR(25), DateTime, 101) AS RecordDate,
SUM(CASE WHEN Value < 700 THEN 1 ELSE 0 END) AS RecordCount
FROM
History
GROUP BY
CONVERT(VARCHAR(25), DateTime, 101)
答案 6 :(得分:-1)
试试这个:
DECLARE @Records TABLE (
[RecordDate] DATETIME,
[RecordCount] INT
)
DECLARE @Date DATETIME = '02/26/2014' -- Enter whatever date you want to start with
DECLARE @EndDate DATETIME = '03/31/2014' -- Enter whatever date you want to stop
WHILE (1=1)
BEGIN
-- Insert the date into the temp table along with the count
INSERT INTO @Records (RecordDate, RecordCount)
VALUES (CONVERT(VARCHAR(25), @Date, 101),
(SELECT COUNT(*) FROM dbo.YourTable WHERE RecordDate = @Date))
-- Go to the next day
@Date = DATEADD(d, 1, @Date)
-- If we have surpassed the end date, break out of the loop
IF (@Date > @EndDate) BREAK;
END
SELECT * FROM @Records
如果您的日期有时间组件,则需要修改此日期以检查SELECT COUNT(*)...
查询中的开始和结束日期。