Postgresql 在连续流程上创建截止日期
我是一名实习生,正在为一些CNC机器指标进行数据采集,我有点被一个特定的查询所困扰,上周才开始使用sql,所以如果这是一个愚蠢的问题,请原谅我 如果机器在23:59之前运行(状态=开),并且我想收集当天的机器小时数,则没有注销时间,因为状态=关闭列尚未记录,因此我无法收集该机器数据。为了解决这个问题,我想记录一个23:59:59的状态关闭时间,然后创建一个新行,该行具有相同的实体ID,状态为“on time of day+1,00:00:01” 这是我到目前为止写的,我错在哪里?我应该使用什么样的触发器、插入、程序、案例等组合?欢迎提出任何建议,我已经试着看了一些参考资料,希望第一部分看起来像这样Postgresql 在连续流程上创建截止日期,postgresql,sql-insert,Postgresql,Sql Insert,我是一名实习生,正在为一些CNC机器指标进行数据采集,我有点被一个特定的查询所困扰,上周才开始使用sql,所以如果这是一个愚蠢的问题,请原谅我 如果机器在23:59之前运行(状态=开),并且我想收集当天的机器小时数,则没有注销时间,因为状态=关闭列尚未记录,因此我无法收集该机器数据。为了解决这个问题,我想记录一个23:59:59的状态关闭时间,然后创建一个新行,该行具有相同的实体ID,状态为“on time of day+1,00:00:01” 这是我到目前为止写的,我错在哪里?我应该使用什么样
CASE
WHEN min(stoff.last_changed) IS NULL
AND now() = '____-__-__ 23:59:59.062538+13'
THEN min(stoff.last_changed) IS now()
ELSE min(stoff.last_changed)
END
<> p>我知道这只是第一个组件,但是它适合于一个更大的选择在一个视图中使用,让我知道如果我需要发布任何其他的< /p> 这是一个相当复杂的查询,因为有几个可能需要考虑的可能性(考虑到CNC机器的物理设置,这些可能并不都适用:)
- 机器可能在午夜运行,因此您需要“插入”午夜开始时间(并将午夜视为前一天的停止时间)
- 机器可能整天都在运行(因此表中根本没有当天的记录)
create table states (
entity_id int,
last_changed timestamp,
state bool
);
insert into states(entity_id, last_changed, state) values
(1, '2019-11-26 01:00', false),
(1, '2019-11-26 20:00', true),
(1, '2019-11-27 01:00', false),
(1, '2019-11-27 02:00', true),
(1, '2019-11-27 22:00', false);
现在查询(它没有看起来那么糟糕!):
您可以在一个查询中完成这一切(不需要触发器、插入等),但对于一天中打开/关闭多次的设备的查询计算运行时,我通常使用窗口函数(相当高级的SQL)。这可能不是必需的;它实际上取决于您可用的数据。如果没有更多的上下文,您当前的代码很难理解;也许您可以添加足够的详细信息,使工作示例为初学者提供上述代码的修改版本(它提供了一个结果,但它是错误的!)。非常感谢@britsThanks!我将SQL放在那里,它直接处理我们的数据库,实际上只是将实体id与开/关状态列配对,并比较时间戳之间的时间(给出状态更改之间经过的时间)。我想实现的是创建一个通过day刷新的表,换句话说,如果一台机器在3天内没有报告关闭状态的更改,那么它将在3行上有条目,这些条目都代表某一天机器正在运行。希望这有点清楚,这很容易理解,再次感谢您选择t是时候帮忙了!我最后向一位同事寻求帮助,结果发现我们想出了与你大致相同的方法。对于任何有类似问题的人,我们写了一个表格,列出了工作日、工作时间(即有员工与无员工)的所有可能组合并将其交叉连接到我们的表中,最后一个_被更改,将任何持续时间都归类为表中可能的行之一
-- Lets start with a range of dates that you want the report for (needed because its possible that there are
-- no entries at all in the states table for a particular date)
with date_range as (
select i::date from generate_series('2019-11-26', '2019-11-29', '1 day'::interval) i
),
-- Get all combinations of machine (entity_id) and date
allMachineDays as (
select distinct states.entity_id, date_range.i as started
from
states cross join date_range),
-- Work out what the state at the start of each day was (if no earlier state available then assume false)
stateAtStartOfDay as (
select
entity_id, started,
COALESCE(
(
select state
from states
where states.entity_id = allMachineDays.entity_id
and states.last_changed<=allMachineDays.started
order by states.last_changed desc limit 1
)
,false) as state
from allMachineDays
)
,
-- Now we can add in the state at the start of each day to the other state changes
statesIncludingStartOfDay as (
select * from stateAtStartOfDay
union
select * from states
),
-- Next we add the time that the state changed
statesWithEnd as (
select
entity_id,
state,
started,
(
select started from statesIncludingStartOfDay substate
where
substate.entity_id = states.entity_id and
substate.started > states.started
order by started asc
limit 1
) as ended
from
statesIncludingStartOfDay states
)
-- finally lets work out the duration
select
entity_id,
state,
started,
ended,
ended - started as duration
from
statesWithEnd states
where
ended is not null -- cut off the last midnight as its no longer needed
order by entity_id,started
with date_range as (
select i::date from generate_series('2019-11-26', '2019-11-29', '1 day'::interval) i
)
select * from date_range