各位大大好,小弟目前工作遇到一個問題如下,請各位大大不吝幫忙,感恩感恩。
使用MSSQL,資料如下。
SQL範例連結
SELECT [paragraph]
,[plc_value]
,[update_at]
FROM [FAB].[dbo].[history]
paragraph plc_value update_at
=第一次=
('open', '53', '2021-12-01 01:00:00'),
('open', '53', '2021-12-01 02:00:00'),
('open', '53', '2021-12-01 03:00:00'),
('standby', '53', '2021-12-01 04:00:00'),
('standby', '53', '2021-12-01 05:00:00'),
('down', '53', '2021-12-01 06:00:00'),
('down', '53', '2021-12-01 07:00:00'),
('down', '53', '2021-12-01 08:00:00'),
=第二次=
('open', '53', '2021-12-02 11:00:00'),
('open', '53', '2021-12-02 12:00:00'),
('open', '53', '2021-12-02 13:00:00'),
('standby', '53', '2021-12-02 14:00:00'),
('standby', '53', '2021-12-02 15:00:00'),
('down', '53', '2021-12-02 16:00:00'),
('down', '53', '2021-12-02 17:00:00'),
('down', '53', '2021-12-02 18:00:00'),
第三筆...
('open', '53', '2021-12-02 19:00:00'),
('open', '53', '2021-12-02 20:00:00'),
('standby', '53', '2021-12-02 20:10:00'),
('standby', '53', '2021-12-02 21:00:00'),
('down', '53', '2021-12-02 21:30:00'),
('down', '53', '2021-12-02 22:00:00')
依此類推,需要取出機台每次運行第一筆[open] ~ 最後一筆[down]的時間,
所以第一筆取出,為以下
('open', '53', '2021-12-01 01:00:00'),
('down', '53', '2021-12-01 08:00:00'),
第二筆
('open', '53', '2021-12-02 11:00:00'),
('down', '53', '2021-12-02 18:00:00'),
第三筆
('open', '53', '2021-12-02 19:00:00'),
('down', '53', '2021-12-02 22:00:00')
...
以上,麻煩各位大大,小弟感激不盡...
假設 : 每一次都會包含 'open'、'down'
CREATE TABLE [dbo].[history](
[paragraph] [varchar](10) NOT NULL,
[plc_value] [varchar](50) NULL,
[update_at] [datetime] NULL);
INSERT INTO [history]
VALUES
-- 第一次
('open', '53', '2021-12-01 01:00:00'),
('open', '53', '2021-12-01 02:00:00'),
('open', '53', '2021-12-01 03:00:00'),
('standby', '53', '2021-12-01 04:00:00'),
('standby', '53', '2021-12-01 05:00:00'),
('down', '53', '2021-12-01 06:00:00'),
('down', '53', '2021-12-01 07:00:00'),
('down', '53', '2021-12-01 08:00:00'),
-- 第二次
('open', '53', '2021-12-02 11:00:00'),
('open', '53', '2021-12-02 12:00:00'),
('open', '53', '2021-12-02 13:00:00'),
('standby', '53', '2021-12-02 14:00:00'),
('standby', '53', '2021-12-02 15:00:00'),
('down', '53', '2021-12-02 16:00:00'),
('down', '53', '2021-12-02 17:00:00'),
('down', '53', '2021-12-02 18:00:00'),
-- 第三次
('open', '53', '2021-12-02 19:00:00'),
('open', '53', '2021-12-02 20:00:00'),
('standby', '53', '2021-12-02 20:10:00'),
('standby', '53', '2021-12-02 21:00:00'),
('down', '53', '2021-12-02 21:30:00'),
('down', '53', '2021-12-02 22:00:00');
方法一 :
;WITH CTE01 AS (
SELECT M.[update_at],M.[paragraph],M.[plc_value],
1+SUM(M.YY) OVER (ORDER BY M.[update_at]) AS NO
FROM (
SELECT [history].*,
CASE
WHEN [paragraph]=LAG([paragraph],1,[paragraph]) OVER (ORDER BY [update_at])
THEN 0 ELSE 1 END AS YY
FROM [history]
WHERE [paragraph] = 'open' OR [paragraph] = 'down') AS M),
CTE02 AS (
SELECT CTE01.*,((NO-1) / 2) + 1 AS [QUOTIENT]
FROM CTE01)
--
SELECT [QUOTIENT],[paragraph],[plc_value],[update_at]
FROM (
SELECT [QUOTIENT],[paragraph],[plc_value],[update_at],
ROW_NUMBER() OVER (PARTITION BY [QUOTIENT] ORDER BY [update_at]) NUN
FROM CTE02) AS XX
WHERE NUN = 1
UNION
SELECT [QUOTIENT],[paragraph],[plc_value],[update_at]
FROM (
SELECT [QUOTIENT],[paragraph],[plc_value],[update_at],
ROW_NUMBER() OVER (PARTITION BY [QUOTIENT] ORDER BY [update_at] DESC) NUN
FROM CTE02) AS ZZ
WHERE NUN = 1
ORDER BY [update_at]
方法二 :
;WITH CTE01 AS (
SELECT M.[update_at],M.[paragraph],M.[plc_value],
1+SUM(M.YY) OVER (ORDER BY M.[update_at]) AS NO
FROM (
SELECT [history].*,
CASE
WHEN [paragraph]=LAG([paragraph],1,[paragraph]) OVER (ORDER BY [update_at])
THEN 0 ELSE 1 END AS YY
FROM [history]
WHERE [paragraph] = 'open' OR [paragraph] = 'down') AS M),
CTE02 AS (
SELECT CTE01.*,((NO-1) / 2) + 1 AS [QUOTIENT]
FROM CTE01)
--
SELECT C.*,D.paragraph,D.update_at_down,DATEDIFF(HOUR,C.update_at_open,D.update_at_down) AS HOUR_TEMP
FROM (
SELECT [QUOTIENT],[paragraph],[plc_value],[update_at] AS [update_at_open]
FROM (
SELECT [QUOTIENT],[paragraph],[plc_value],[update_at],
ROW_NUMBER() OVER (PARTITION BY [QUOTIENT] ORDER BY [update_at]) NUN
FROM CTE02) AS XX
WHERE NUN = 1) AS C
LEFT JOIN (
SELECT [QUOTIENT],[paragraph],[plc_value],[update_at] AS [update_at_down]
FROM (
SELECT [QUOTIENT],[paragraph],[plc_value],[update_at],
ROW_NUMBER() OVER (PARTITION BY [QUOTIENT] ORDER BY [update_at] DESC) NUN
FROM CTE02) AS ZZ
WHERE NUN = 1
) AS D ON D.[QUOTIENT] = C.[QUOTIENT]
ORDER BY C.[update_at_open]
假設你的機台稼動率為8小時
每小時通知一次機台狀態
開機open關機down
跨夜為午夜12點
SQL如下~
select [paragraph]
,[plc_value]
,(
case when [paragraph] = 'open'
then min([update_at])
else max([update_at])
end
) [update_at]
from (
SELECT Convert(int,(ROW_NUMBER() OVER (PARTITION BY Convert(date,[update_at] ) ORDER BY [update_at] ) - 1) / 8) GroupSort
,*
FROM [history]
) k
where [paragraph] in('open','down')
group by Convert(date,[update_at] )
,GroupSort
,[paragraph]
,[plc_value]
order by min([update_at])
另外一種方式,使用PG為例.
create table it0112 (
paragraph text
, its timestamp(0)
);
insert into it0112 values
('open', '2021-12-01 01:00:00'),
('open', '2021-12-01 02:00:00'),
('open', '2021-12-01 03:00:00'),
('standby', '2021-12-01 04:00:00'),
('standby', '2021-12-01 05:00:00'),
('down', '2021-12-01 06:00:00'),
('down', '2021-12-01 07:00:00'),
('down', '2021-12-01 08:00:00'),
('open', '2021-12-02 11:00:00'),
('open', '2021-12-02 12:00:00'),
('open', '2021-12-02 13:00:00'),
('standby', '2021-12-02 14:00:00'),
('standby', '2021-12-02 15:00:00'),
('down', '2021-12-02 16:00:00'),
('down', '2021-12-02 17:00:00'),
('down', '2021-12-02 18:00:00'),
('open', '2021-12-02 19:00:00'),
('open', '2021-12-02 20:00:00'),
('standby', '2021-12-02 20:10:00'),
('standby', '2021-12-02 21:00:00'),
('down', '2021-12-02 21:30:00'),
('down', '2021-12-02 22:00:00');
---
with t1 as(
select paragraph, its
, lag(paragraph) over(order by its)
, lead(paragraph) over(order by its)
from it0112
where paragraph in ('open', 'down')
), t2 as (
select paragraph, its
, case
when paragraph = 'open'
and (lag is NULL or lag = 'down')
then 'head'
when paragraph = 'down'
and (lead is NULL or lead = 'open')
then 'tail'
else 'not'
end as hort
from t1
)
select *
, case
when hort = 'head'
then '開工->'
when hort = 'tail'
and lead(its) over(order by its) is null
then '休眠中'
else '休息->'
end as wrkstat
, (lead(its) over(order by its) - its) as period
from t2
where hort in ('head', 'tail');
paragraph | its | hort | wrkstat | period
-----------+---------------------+------+---------+----------------
open | 2021-12-01 01:00:00 | head | 開工-> | 07:00:00
down | 2021-12-01 08:00:00 | tail | 休息-> | 1 day 03:00:00
open | 2021-12-02 11:00:00 | head | 開工-> | 07:00:00
down | 2021-12-02 18:00:00 | tail | 休息-> | 01:00:00
open | 2021-12-02 19:00:00 | head | 開工-> | 03:00:00
down | 2021-12-02 22:00:00 | tail | 休眠中 | NULL
(6 rows)