【问题标题】:How do I fill in missing dates as rows and give other values? (exceptional case)如何将缺失的日期填写为行并提供其他值? (例外情况)
【发布时间】:2017-05-09 07:25:17
【问题描述】:

我有很多关于这个问题的背景的解释,所以请耐心等待。

在我的公司,我们有一个 SQL Server 数据库,我在 Management Studio 2014 工作。 我们有一个名为 Jobstatistics 的表,它显示在每个一小时的时间间隔内完成了多少作业。 The table looks like this

车站领域基本上是可以在不同区域完成工作的。

如您所见,某些行在某些时间间隔内丢失,这是因为该表填充数据的方式。为了填充这个表,我们运行了一个脚本,它查看另一个表并聚合此时间间隔内所有日期的作业量。换句话说,如果没有任何作业,则不会插入一行,因为不会插入任何内容(其他表中没有行可以聚合任何作业)。

我在这里要做的是用 0 作为 Jobs 的数量填充这些额外的间隔。因此,每天和每个站点总会有 24 个间隔(小时)。最重要的是,我们已经设定了我们想要实现的目标,我在另一个名为 JobstatisticsTargets 的表中声明了这些目标,您可以调用日历表来加入 Jobstatistics 表。

The calender table looks like this

我尝试进行左连接或右连接,以便填充缺失的间隔,并且作业至少会获得 NULL 值,但连接子句并没有达到我的预期。

这是我的尝试

SELECT a.[Station], a.[Interval], a.[Jobs], b.[28JPH], b.[35JPH]
FROM [JobStatistics] a
RIGHT JOIN [JobStatisticsTargets] b
  ON CONVERT(VARCHAR(10),a.Interval,108) = b.Interval
WHERE DATEDIFF(DAY, a.Interval, GETDATE()) < 12
  AND Station LIKE '138010'
ORDER BY a.Station, a.Interval

LEFT JOIN 的作用与我期望的普通连接完全一样,它不会附加任何带有 NULL 值的间隔。 (查询只针对一个站和几天,所以我可以轻松测试)

非常感谢任何帮助。我会定期检查这个主题,所以如果你有任何关于上下文的问题,请务必提出,我会尽力解释它!

编辑 在一些帮助下,查询现在看起来像这样

SELECT a.[Station], b.[Interval], a.[Jobs], b.[28JPH], b.[35JPH]
FROM [JobStatistics] a
RIGHT JOIN [JobStatisticsTargets] b
  ON CONVERT(VARCHAR(10),a.Interval,108) = b.Interval
    AND CONVERT(VARCHAR(10),a.Interval,110) = CONVERT(VARCHAR(10),GETDATE(),110)
    AND Station LIKE '138010'
ORDER BY b.Interval

我现在过滤今天的日期,否则额外的行根本不是我想要的。问题是我不知道填写我的电台的简单方法。我想我需要一个子查询,还是有其他方法?

现在的问题也是我无法针对不同的电台进行此查询。我希望每个站点有 24 行代表所有间隔,但结果是:

Station   Interval    Jobs    28JPH   35JPH
NULL      00:30:00    NULL    0       0
NULL      01:30:00    NULL    0       0
NULL      02:30:00    NULL    0       0
NULL      03:30:00    NULL    0       0
134040    04:30:00    2       0       0
136060    04:30:00    2       0       0
131080    04:30:00    2       0       0
138010    05:30:00    2       0       0
NULL      06:30:00    NULL    0       0
NULL      07:30:00    NULL    28      35
NULL      08:30:00    NULL    28      35
...

【问题讨论】:

  • 您需要使用右连接,因为缺少的值在左表上。
  • 我试过了,这并没有改变任何输出。这就是为什么我有点困惑。加入没有按照我的预期进行。

标签: sql-server database join


【解决方案1】:

您从表中筛选出哪些行可能不会出现在连接结果中:>>>AND St​​ation LIKE '138010' 您应该更改您的查询并将此条件放在 ON CLAUSE,而不是 WHERE

【讨论】:

  • 我确实得到了一个输出,但就好像它是一个普通的 JOIN 子句(只有左表中具有相应目标的行)。我尝试将条件放在 on 子句中,输出仍然保持不变。
  • 还有一个条件 DATEDIFF(DAY, a.Interval, GETDATE())
  • 我明白了,非常感谢您的回答。我觉得这肯定是朝着正确方向迈出的一步。但是,我怎样才能像这样填写 NULL 值?我至少应该能够填写间隔值,否则我将不得不专门为每一天进行此查询,并用右表中的间隔填写它。
【解决方案2】:

检查此脚本并告诉我,

declare @t table(interval datetime,jobs int)
insert into @t VALUES('2017-04-28 05:30',1),('2017-04-28 06:30',5),('2017-04-29 06:30',5)
--select * from @t
;With CTE as
(
  select cast('00:00' as time) as IntervalTime
  union ALL
  select DATEADD(MINUTE,30,IntervalTime)
  from cte
  where IntervalTime<'23:30'
)
,CTE1 AS(
select interval,jobs
,dense_rank()over( order by cast(interval as date))rn
from @t
)
select * FROM
(
select distinct  case when t.interval is null then 
 DATEADD(day, DATEDIFF(day, 0, 
 (select top 1 interval from cte1 where rn=n.number)), cast(c.IntervalTime as datetime))
 else t.interval end Newinterval,isnull(t.jobs,0) Jobs

from CTE c
left join  cte1 t
on  c.IntervalTime=cast(t.interval as time)
cross apply(select  number from master.dbo.spt_values
     where name is null and number<=(select max(rn) from cte1))n
)t4
where Newinterval is not null

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-03
    • 2020-12-29
    • 2018-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-05
    相关资源
    最近更新 更多