【问题标题】:Counting on 2 Date columns计算 2 个日期列
【发布时间】:2020-04-06 02:21:02
【问题描述】:

所以我有 2 个日期列,开始和结束。我要完成的是每天的库存,这将追溯到 2020 年初,因此我拥有这些字段:

开始日期、当天新增的数量、当天关闭的数量以及前几天的现有打开数量。我派生的基本数据结构是开始日期、结束日期、请求类型(如果开始日期 = 报告日期且结束日期为空,则“新添加”,如果结束日期不为空,则“工作已结束”,如果开始日期为小于报告日期然后“现有打开”。问题是这些取决于报告日期和打开/关闭日期之间的相关性。我需要能够按日期分组并给出每天的计数。我试过这些2 个解决方案,并没有像我希望的那样工作,因为它们与我的情况略有不同。(Count Function on Multiple Columns by Date (SQL Server)Get count on two different date columns and group by date)。当我总结时,我需要根据当前日期每天进行计数库存和前一天的现有物品。

我的基本数据结构是这样的,是假数据:

+----+------------+-----------+---+
| ID | StartDate  |  EndDate  |   |
+----+------------+-----------+---+
|  1 | 1/1/2020   |  NULL     |   |
|  2 | 12/1/2019  | 1/1/2020  |   |
|  3 | 1/1/2020   |  1/3/2020 |   |
|  4 | 12/17/2019 | 1/2/2020  |   |
+----+------------+-----------+---+

预期结果:

+-------------+---------+-----------------+-----------+--+--+------+
| Report Date | NewAdds |    ExistingOpen |    Closed |  |  |      |
+-------------+---------+-----------------+-----------+--+--+------+
| 1/1/2020    |       2 |          1       |         1 |  |  |    |
| 1/2/2020    |       0 |          1      |         1 |  |  |     |
| 1/3/2020    |       0 |          1      |         1 |  |  |     |
+-------------+---------+-----------------+-----------+--+--+------+

【问题讨论】:

  • 50% 清晰。我算什么?你应该给出至少 10 天的数据。

标签: sql-server


【解决方案1】:
set @report_start = '20200101';
set @report_end = '20200103';

select
    d.dt,
    count(case when t.start_dt = d.dt then 1 end) as Adds,
    count(case when d.dt > t.start_dt and d.dt < t.end_dt as Existing,
    count(case when t.end_dt = d.dt then 1 end) as Closed
from T t inner join Dates d on d.dt <= coalesce(t.end_dt, @report_end)
where d.dt between @report_start and @report_end
group by d.dt;

创建一个日期表并加入它。那时计数相当容易。

这是一个坏主意,因为您需要计算所有日期。我也不知道空结束日期是什么意思。如果这是我在手机上输入时的草率,请致歉。

【讨论】:

  • NULL date 表示请求仍然打开。这就是为什么我需要能够计算这些,直到它被关闭。因此,如果第一行延续到第二天,我可以在输出中说它是 Existing。
  • 这几乎可以正常工作,除了 Existing 没有被正确计算,因为截至今天它说有 0 个现有但我在 Excel 中手动计数仍有超过 63,000 个请求处于打开状态(旧库存从一天到天) 。我现在正试图弄清楚为什么。这些仍然有 NULL 关闭天,这意味着它们仍然是开放的请求。感谢您协助我处理这个疯狂的请求。
【解决方案2】:

这是修复处理任何报告日期的逻辑的解决方案的开始:

If Start_date = report_date and (end_date is null or  end_date > report date) then 'New Add'

if end_date is not null and end_date <= report_date then 'Work Closed'

if Start_Date < report_date  and (end_date is null or end_date > report_date then 'Existing Open'

您需要一个可以为您提供三个值之一的 case 表达式。

一旦您让它适用于单个报告日期,您就可以使用此解决方案生成一系列报告日期并将其加入您的表格:Generate Dates between date ranges

【讨论】:

    【解决方案3】:

    要实施我的解决方案,请添加一个用于管理日历的表格

    你必须做几个步骤来解决这个问题:

    1. 确定每个日历间隔打开哪些任务 (NewAddTask)
    2. 按时间间隔计算打开的任务总数 (TotalNewAddTask)
    3. 确定每个日历间隔的关闭任务 (ClosedTask)
    4. 按时间间隔计算关闭任务总数(TotalClosedTask)
    5. 计算间隔组合的时间表 (ExistingOpenCalendar)
    6. 确定每个日历间隔的现有打开的任务 (ExistingOpenDetail)
    7. 按时间间隔计算现有打开任务总数(TotalExistingOpenTask)
    8. 我终于把所有的总数和日历结合起来了

      with NewAddTask as
      (
              SELECT IdCalendar,IdTask
              FROM
              Calendar CROSS JOIN Task 
              where StarDate  between FirstDate and LastDate
      ),
      TotalNewAddTask as
      (
              select IdCalendar,count(IdTask) as Total
              from NewAddTask 
              group by IdCalendar
      ),
      ClosedTask as
      (
              SELECT IdCalendar,IdTask
              FROM
              Calendar CROSS JOIN Task 
              where isnull(CloseDate,'2020-12-31') between FirstDate and LastDate
      ),
      TotalClosedTask as
      (
              select IdCalendar,count(IdTask) as Total
              from ClosedTask 
              group by IdCalendar
      ),
      ExistingOpenCalendar as 
      (
              SELECT 
              Calendarend.IdCalendar ,
              CalendarStart.FirstDate,
              Calendarend.LastDate
              FROM
              Calendar as CalendarStart CROSS JOIN Calendar as Calendarend 
              where 
              CalendarStart.FirstDate<Calendarend.LastDate
      )
      , ExistingOpenDetail as
      (
              select ExistingOpenCalendar.IdCalendar,Task.IdTask 
              from ExistingOpenCalendar CROSS JOIN Task 
              where StarDate  between FirstDate and LastDate
              and not (isnull(CloseDate,'2020-12-31') between FirstDate and LastDate)
              and (CloseDate is null  or (CloseDate < LastDate))
      )
      ,TotalExistingOpenTask  as
      (
              select IdCalendar,count(IdTask) as Total 
              from ExistingOpenDetail
              group by IdCalendar
      )
      select 
      Calendar.IdCalendar,Calendar.FirstDate ,
      isnull(TotalNewAddTask.Total,0)as NewAddTask,
      isnull(TotalClosedTask.Total,0)as ClosedTask,
      isnull(TotalExistingOpenTask.Total,0)as ExistingOpen
      from Calendar 
      left join TotalNewAddTask on Calendar.IdCalendar=TotalNewAddTask.IdCalendar
      left join TotalClosedTask on Calendar.IdCalendar=TotalClosedTask.IdCalendar
      left join TotalExistingOpenTask on Calendar.IdCalendar=TotalExistingOpenTask.IdCalendar
      

    此查询满足条件

    in this example you can find example

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-03
      • 2016-08-21
      • 1970-01-01
      • 2017-11-01
      相关资源
      最近更新 更多