Reputation: 23
I have a SQL table which holds transactions of products and cumulative total of packed products each minute from a machine.
I'm trying to summarize this table (in a sql query) into product runs.
Create table and insert data....
CREATE TABLE [dbo].[Test](
[ID] [nchar](10) NULL,
[Product] [varchar](20) NULL,
[datetime] [datetime] NULL,
[Cumulative_Packed] [int] NULL
) ON [PRIMARY]
GO
INSERT [dbo].[Test] ([ID], [Product], [datetime], [Cumulative_Packed]) VALUES (N'1 ', N'Item1', CAST(N'2019-11-14T14:15:00.000' AS DateTime), 10)
INSERT [dbo].[Test] ([ID], [Product], [datetime], [Cumulative_Packed]) VALUES (N'2 ', N'Item1', CAST(N'2019-11-14T14:16:00.000' AS DateTime), 22)
INSERT [dbo].[Test] ([ID], [Product], [datetime], [Cumulative_Packed]) VALUES (N'3 ', N'Item1', CAST(N'2019-11-14T14:17:00.000' AS DateTime), 35)
INSERT [dbo].[Test] ([ID], [Product], [datetime], [Cumulative_Packed]) VALUES (N'4 ', N'Item1', CAST(N'2019-11-14T14:18:00.000' AS DateTime), 40)
INSERT [dbo].[Test] ([ID], [Product], [datetime], [Cumulative_Packed]) VALUES (N'5 ', N'Item1', CAST(N'2019-11-14T14:19:00.000' AS DateTime), 40)
INSERT [dbo].[Test] ([ID], [Product], [datetime], [Cumulative_Packed]) VALUES (N'6 ', N'Item1', CAST(N'2019-11-14T14:20:00.000' AS DateTime), 40)
INSERT [dbo].[Test] ([ID], [Product], [datetime], [Cumulative_Packed]) VALUES (N'7 ', N'Item1', CAST(N'2019-11-14T14:21:00.000' AS DateTime), 0)
INSERT [dbo].[Test] ([ID], [Product], [datetime], [Cumulative_Packed]) VALUES (N'8 ', N'Item1', CAST(N'2019-11-14T14:22:00.000' AS DateTime), 0)
INSERT [dbo].[Test] ([ID], [Product], [datetime], [Cumulative_Packed]) VALUES (N'9 ', N'Item1', CAST(N'2019-11-14T14:23:00.000' AS DateTime), 0)
INSERT [dbo].[Test] ([ID], [Product], [datetime], [Cumulative_Packed]) VALUES (N'10 ', N'Item2', CAST(N'2019-11-14T14:24:00.000' AS DateTime), 12)
INSERT [dbo].[Test] ([ID], [Product], [datetime], [Cumulative_Packed]) VALUES (N'11 ', N'Item2', CAST(N'2019-11-14T14:25:00.000' AS DateTime), 18)
INSERT [dbo].[Test] ([ID], [Product], [datetime], [Cumulative_Packed]) VALUES (N'12 ', N'Item2', CAST(N'2019-11-14T14:26:00.000' AS DateTime), 18)
INSERT [dbo].[Test] ([ID], [Product], [datetime], [Cumulative_Packed]) VALUES (N'13 ', N'Item2', CAST(N'2019-11-14T14:27:00.000' AS DateTime), 22)
INSERT [dbo].[Test] ([ID], [Product], [datetime], [Cumulative_Packed]) VALUES (N'14 ', N'Item2', CAST(N'2019-11-14T14:28:00.000' AS DateTime), 22)
INSERT [dbo].[Test] ([ID], [Product], [datetime], [Cumulative_Packed]) VALUES (N'15 ', N'Item1', CAST(N'2019-11-14T14:29:00.000' AS DateTime), 0)
INSERT [dbo].[Test] ([ID], [Product], [datetime], [Cumulative_Packed]) VALUES (N'16 ', N'Item1', CAST(N'2019-11-14T14:30:00.000' AS DateTime), 7)
INSERT [dbo].[Test] ([ID], [Product], [datetime], [Cumulative_Packed]) VALUES (N'17 ', N'Item1', CAST(N'2019-11-14T14:31:00.000' AS DateTime), 30)
INSERT [dbo].[Test] ([ID], [Product], [datetime], [Cumulative_Packed]) VALUES (N'18 ', N'Item1', CAST(N'2019-11-14T14:32:00.000' AS DateTime), 38)
INSERT [dbo].[Test] ([ID], [Product], [datetime], [Cumulative_Packed]) VALUES (N'19 ', N'Item1', CAST(N'2019-11-14T14:33:00.000' AS DateTime), 38)
INSERT [dbo].[Test] ([ID], [Product], [datetime], [Cumulative_Packed]) VALUES (N'20 ', N'Item1', CAST(N'2019-11-14T14:34:00.000' AS DateTime), 38)
INSERT [dbo].[Test] ([ID], [Product], [datetime], [Cumulative_Packed]) VALUES (N'21 ', N'Item1', CAST(N'2019-11-14T14:35:00.000' AS DateTime), 38)
Upvotes: 0
Views: 603
Reputation: 1269445
I think you want lead()
and lag()
to identify the starts and stops. For your data:
select row_number() over (order by min(datetime)) as run_order,
product, min(datetime), max(datetime),
max(cumulative_packed)
from (select t.*,
sum(case when prev_cp = 0 or prev_cp is null then 1 else 0 end) over (partition by product order by datetime) as rungrp
from (select t.*,
lag(cumulative_packed) over (partition by product order by datetime) as prev_cp,
lead(cumulative_packed) over (partition by product order by datetime) as next_cp
from t
) t
where (prev_cp = 0 or prev_cp is null) or -- is start
(next_cp = cp or next_cp = 0 or next_cp is null) -- is stop
) t
group by rungrp, product
order by rungrp, product, min(datetime);
EDIT:
Your data seems to require duplicate removal. From what I follow, you just need the first time the value changes. This can be handled with one additional layer of subqueries:
select row_number() over (order by min(datetime)) as run_order,
product, min(datetime), max(datetime),
max(cumulative_packed)
from (select t.*,
sum(case when prev_cp = 0 or prev_cp is null then 1 else 0 end) over (partition by product order by datetime) as rungrp
from (select t.*,
lag(cumulative_packed) over (partition by product order by datetime) as prev_cp,
lead(cumulative_packed) over (partition by product order by datetime) as next_cp
from (select t.*,
lag(cumulative_packed) over (partition by product order by datetime) as first_prev_cp
from t
) t
where first_prev_cp is null or first_prev_cp <> cumulative_packed
) t
where (prev_cp = 0 or prev_cp is null) or -- is start
(next_cp = cp or next_cp = 0 or next_cp is null) -- is stop
) t
group by rungrp, product
order by rungrp, product, min(datetime);
Upvotes: 1