【问题标题】:Fill date gaps in SQL query with zeros用零填充 SQL 查询中的日期空白
【发布时间】:2016-10-05 10:52:20
【问题描述】:

我有以下结构(来自表之间的一些连接等),将用于生成图表。

某些 ID 没有所有日期的数据,这会导致图表中出现一些虚线。

问题是,如何为每个 ID 添加缺失的日期并用零填充其数据单元格?

作为脚本:

(67, '2016-09-28 00:00:00.000',1),
(178, '2016-09-28 00:00:00.000',6),
(42, '2016-09-25 00:00:00.000',1),
(66, '2016-09-25 00:00:00.000',122),
(67, '2016-09-25 00:00:00.000',2),
(10, '2016-09-24 00:00:00.000',5),
(13, '2016-09-24 00:00:00.000',4),
(66, '2016-09-24 00:00:00.000',198),
(67, '2016-09-24 00:00:00.000',15),
(178, '2016-09-24 00:00:00.000',4),
(10, '2016-09-23 00:00:00.000',1),
(13, '2016-09-23 00:00:00.000',2),
(42, '2016-09-23 00:00:00.000',4),
(66, '2016-09-23 00:00:00.000',208),
(67, '2016-09-23 00:00:00.000',15)

【问题讨论】:

标签: sql sql-server tsql


【解决方案1】:

日历表和 CROSS JOIN 的另一种方式:

;WITH YourQueryOutput AS (
--put your select statement here
), calendar AS (
SELECT  CAST(MIN(RoundedTime) as datetime) as d,
        MAX(RoundedTime) as e
FROM YourQueryOutput
UNION ALL
SELECT  DATEADD(day,1,d),
        e
FROM calendar
WHERE d < e
)

SELECT  t.ID,
        c.d,
        COALESCE(t1.[data],0) as [data]
FROM calendar c
CROSS JOIN (
    SELECT DISTINCT ID
    FROM YourQueryOutput
    ) t
LEFT JOIN YourQueryOutput t1
    ON t.ID = t1.ID and t1.RoundedTime = c.d
ORDER BY t.ID, c.d
OPTION(MAXRECURSION 0)

您提供的样本的输出

ID  d                       data
10  2016-09-23 00:00:00.000 1
10  2016-09-24 00:00:00.000 5
10  2016-09-25 00:00:00.000 0
10  2016-09-26 00:00:00.000 0
10  2016-09-27 00:00:00.000 0
10  2016-09-28 00:00:00.000 0
...
178 2016-09-23 00:00:00.000 0
178 2016-09-24 00:00:00.000 4
178 2016-09-25 00:00:00.000 0
178 2016-09-26 00:00:00.000 0
178 2016-09-27 00:00:00.000 0
178 2016-09-28 00:00:00.000 6

【讨论】:

    【解决方案2】:

    这是一种方法:

    with t as (
          <your query here>
         )
    select i.id, rt.roundedtime, coalesce(data, 0) as data
    from (select distinct id from t) i cross join
         (select distinct roundedtime rt from t) rt left join
         t
         on t.id = i.id and t.roundedtime = rt.roundedtime;
    

    换句话说,使用cross join 创建日期列表和ids。然后使用left join 引入您的数据。

    此查询对您的原始数据使用 select distinct 来获取日期和 ID 列表。可能有更有效的方法来获取这些列表中的每一个。

    【讨论】:

    • 感谢您的反馈。问题是并未列出所有日期,因此它们不会显示在您的查询中
    【解决方案3】:

    您可以在使用 join 的 SELECT 语句中检查 ISNULL(YourDataColumn,0)

    示例:

    SELECT
        Q.QuestionId,
        Q.SenderType,
        ISNULL(Q.Data,0) AS Data
    FROM @tblQuestion Q
    LEFT JOIN @tblTeacher T ON Q.SenderId=T.Id AND Q.SENDERTYPE='TEACHER'
    LEFT JOIN @tblInstitute I ON Q.SenderId=I.Id AND Q.SENDERTYPE='INSTITUTE'
    

    如果加入后没有可用数据,则在 Select Statement Data column return 0 上方输入

    【讨论】:

    • 据我了解,该查询中没有一些 ID,OP 需要向它们显示缺少日期和零。
    • 据我了解,在输出表中没有针对某个日期的数据,因此图表无法正确呈现,因此如果图表接受 int 然后 0 其他值,则应该有一些数据,根据数据类型
    • @gofr1:没错,在那个查询中,ID 和 RoundedTime 都有差距,所以 ISNULL 在这里不会有太大作用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-26
    • 1970-01-01
    • 1970-01-01
    • 2021-03-19
    • 1970-01-01
    相关资源
    最近更新 更多