0

给定表格

asset
  col - id
date_sequence
  col - date
daily_history
  col - date
  col - num_error_seconds
  col - asset_id
historical_event
  col - start_date
  col - end_date
  col - asset_id

我正在尝试计算给定时间范围内所有资产的所有每日 num_error_seconds,以便按天显示“未出错的百分比”。问题是,如果历史事件涉及的资产的 end_date 超出 sql 查询范围,则应忽略 daily_history,并且应为该资产使用默认值 86400 秒(error_seconds 的一天)

我不使用history_event的查询是:

select ds.date, 
  IF(count(dh.time) = 0, 
    100, 
    100 - (100*sum(dh.num_error_seconds) / (86400 * count(*)))
  ) percent
  from date_sequence ds 
  join asset a
  left join daily_history dh on dh.date = ds.date and dh.asset_id=a.asset_id
  where ds.date >= in_start_time and ds.date <= in_end_time
  group by ds.thedate;

在此基础上进行构建超出了我的 SQL 知识范围。由于聚合函数,我不能简单地为与 end_date 超过 in_end_time 的事件关联的每个资产注入 86400 秒。

Sample Data
Asset
1
2

Date Sequence
2013-09-01
2013-09-02
2013-09-03
2013-09-04

Daily History
2013-09-01, 1400, 1
2013-09-02, 1501, 1
2013-09-03, 1420, 1
2013-09-04, 0, 1
2013-09-01, 10000, 2
2013-09-02, 20000, 2
2013-09-03, 30000, 2
2013-09-04, 40000, 2

Historical Event
start_date, end_date, asset_id
2013-09-03 12:01:03, 2014-01-01 00:00:00, 1

我希望通过此示例数据看到的是这些资产出错的时间百分比

2013-09-01 => 100 - (100*(1400 + 10000))/(86400*2)
2013-09-02 => 100 - (100*(1501 + 20000))/(86400*2)
2013-09-03 => 100 - (100*(1420 + 30000))/(86400*2)
2013-09-04 => 100 - (100*(0 + 40000))/(86400*2)

例外:有一个历史事件应该优先考虑。它发生在 9/3 并且是开放式的(有一个未来的结束日期,因此计算将更改为:

2013-09-01 => 100 - (100*(1400 + 10000))/(86400*2)
2013-09-02 => 100 - (100*(1501 + 20000))/(86400*2)
2013-09-03 => 100 - (100*(86400 + 30000))/(86400*2)
2013-09-04 => 100 - (100*(86400 + 40000))/(86400*2)

如果历史事件的 start_date 早于 'in_end_time' 而 end_time 在 in_end_time 之后,则资产 1 的 num_error_seconds 会被一整天的错误秒数覆盖

这可以在一个查询中完成吗?还是我需要使用初始查询暂存数据?

4

1 回答 1

1

我想你在追求这样的事情:

Select
    ds.date,
    100 - 100 * Sum(
        case
            when he.asset_id is not null then 86400 -- have a historical_event
            when dh.num_error_seconds is null then 0 -- no daily_history record
            else dh.num_error_seconds
        end
    ) / 86400 / count(a.id) as percent -- need to divide by number of assets
From
    date_sequence ds
        cross join
    asset a
        left outer join
    daily_history dh 
        on a.id = dh.asset_id and
           ds.date = dh.date
        left outer join (
            select distinct -- avoid counting multiple he records
                asset_id
            from
                historical_event he
            Where
                he.end_date > in_end_time
        ) he
        on a.id = he.asset_id    
Where
    ds.date >= in_start_time and
    ds.date <= in_end_time -- I'd prefer < here
Group By
    ds.date

示例小提琴

于 2013-09-18T23:20:07.830 回答