Home > database >  Calculate Elapsed Time For Each Unit Grouped By Hour
Calculate Elapsed Time For Each Unit Grouped By Hour

Time:07-22

I'm using SQL Server 2012 (v11.0.7001.0).

I am tasked with calculating automagically the hourly production target for one assembly line. Any guidance is much appreciated, as I am banging my head against a wall.

This assembly line can build a mix of three different units, each with a different takt time to meet demand.

Takt Time = Total Available Production Time / Customer Demand

The units are produced serially and for each unit produced, a datetime is wrote to a table with the unit number. The takt times are stored in another table.

I am able to query each datetime a unit was produced and that unit's takt time.

SELECT 
    p.Timestamp AS ProducedDT, 
    (SELECT TaktTime 
     FROM skutakttime 
     WHERE Material = p.SKU) AS TaktTime 
FROM 
    productionLog p
WHERE 
    p.Timestamp BETWEEN '2022-07-20 06:00:00' 
                    AND (SELECT MAX([Timestamp]) 
                         FROM productionLog 
                         WHERE [CostCenter] = 'Line1' AND [Station] = 3)
    AND [CostCenter] = 'Line1' 
    AND [Station] = 3

My query returns this:

ProducedDT                  TaktTime
-------------------------------------
2022-07-20 06:17:19.303     98
2022-07-20 06:20:03.507     98
2022-07-20 06:21:31.263     98
2022-07-20 06:23:42.313     98
2022-07-20 06:25:07.040     98
2022-07-20 06:29:38.893     98
2022-07-20 06:31:09.333     98
2022-07-20 06:32:47.533     98
2022-07-20 06:34:19.613     98
2022-07-20 06:35:54.930     98
2022-07-20 06:38:36.850     98
2022-07-20 06:40:17.380     98
2022-07-20 06:41:38.297     98
2022-07-20 06:43:03.930     98
2022-07-20 06:44:39.800     98
2022-07-20 06:46:31.313     98
2022-07-20 06:48:21.487     98
2022-07-20 06:51:25.537     98
2022-07-20 06:53:02.043     98
2022-07-20 06:57:32.623     98
2022-07-20 06:59:02.220     98
2022-07-20 07:00:29.117     98
2022-07-20 07:03:04.730     98
2022-07-20 07:05:33.073     98
2022-07-20 07:07:34.690     98
2022-07-20 07:08:58.740     98
2022-07-20 07:10:25.113     98
2022-07-20 07:11:53.813     98
2022-07-20 07:13:24.540     98
2022-07-20 07:14:44.077     98
2022-07-20 07:16:18.870     98
2022-07-20 07:17:48.630     98
2022-07-20 07:19:21.657     98
2022-07-20 07:21:00.763     98
2022-07-20 07:22:52.070     98
2022-07-20 07:25:28.013     98
2022-07-20 07:27:19.447     98
2022-07-20 07:29:03.943     98
2022-07-20 07:30:39.520     98
2022-07-20 07:32:36.923     98
2022-07-20 07:34:44.183     98
2022-07-20 07:36:16.870     98
2022-07-20 07:37:49.780     98
2022-07-20 07:39:40.923     98
2022-07-20 07:41:33.030     98
2022-07-20 07:43:03.460     98
2022-07-20 07:55:06.543     98
2022-07-20 07:56:50.200     98
2022-07-20 07:58:23.000     98
2022-07-20 08:18:41.510     98
2022-07-20 08:22:47.150     98
2022-07-20 08:24:24.610     98
2022-07-20 08:25:59.843     98
2022-07-20 08:27:35.233     98
2022-07-20 08:29:12.917     98
2022-07-20 08:31:00.070     98
2022-07-20 08:32:44.520     98
2022-07-20 08:34:29.833     98
2022-07-20 08:36:13.337     98
2022-07-20 08:38:33.440     98
2022-07-20 08:40:13.183     98
2022-07-20 08:41:49.987     98
2022-07-20 08:43:29.773     98
2022-07-20 08:45:18.027     98
2022-07-20 08:47:00.277     98
2022-07-20 08:48:48.383     98
2022-07-20 08:50:26.653     98
2022-07-20 08:52:03.557     98
2022-07-20 08:54:06.760     98
2022-07-20 08:55:47.360     98
2022-07-20 08:57:24.213     98
2022-07-20 08:59:09.997     98
2022-07-20 09:00:46.923     98
2022-07-20 09:04:29.803     98
2022-07-20 09:06:06.763     98
2022-07-20 09:07:39.797     98
2022-07-20 09:09:12.967     98
2022-07-20 09:12:56.330     98
2022-07-20 09:14:46.083     98
2022-07-20 09:16:33.160     98
2022-07-20 09:18:27.647     98
2022-07-20 09:20:21.643     98
2022-07-20 09:22:17.887     98
2022-07-20 09:28:53.380     98
2022-07-20 09:31:55.660     98
2022-07-20 10:24:05.053     98
2022-07-20 10:27:41.350     98
2022-07-20 10:29:17.557     98
2022-07-20 10:31:08.093     98
2022-07-20 10:32:33.980     98
2022-07-20 10:34:03.780     98
2022-07-20 10:35:41.880     98
2022-07-20 10:37:23.760     98
2022-07-20 10:39:08.803     98
2022-07-20 10:41:18.667     98
2022-07-20 10:45:44.873     98
2022-07-20 10:47:05.563     98
2022-07-20 10:48:36.183     98
2022-07-20 10:51:30.743     98
2022-07-20 10:52:45.307     98
2022-07-20 10:54:10.483     98
2022-07-20 10:56:47.223     98
2022-07-20 10:58:41.080     98
2022-07-20 10:59:55.767     98
2022-07-20 11:01:10.773     98
2022-07-20 11:03:35.827     98
2022-07-20 11:05:14.577     98
2022-07-20 11:06:36.073     98
2022-07-20 11:08:00.840     98
2022-07-20 11:09:31.973     98
2022-07-20 11:11:19.847     98
2022-07-20 11:12:51.637     98
2022-07-20 11:14:18.457     98
2022-07-20 11:15:44.730     98
2022-07-20 11:22:20.520     98
2022-07-20 11:26:20.517     98
2022-07-20 11:27:43.163     98
2022-07-20 11:30:12.613     98
2022-07-20 11:34:13.937     98
2022-07-20 11:35:48.040     98
2022-07-20 11:37:27.660     98
2022-07-20 11:38:56.573     98
2022-07-20 11:40:22.260     98
2022-07-20 11:41:47.933     98
2022-07-20 11:43:24.913     98
2022-07-20 11:45:15.350     98
2022-07-20 11:46:34.750     98
2022-07-20 11:57:22.407     75
2022-07-20 11:58:54.587     75
2022-07-20 12:33:57.977     75
2022-07-20 12:37:44.883     75
2022-07-20 12:39:19.243     75
2022-07-20 12:40:41.180     75
2022-07-20 12:41:58.140     75
2022-07-20 12:43:26.903     75
2022-07-20 12:45:01.270     75
2022-07-20 12:46:17.687     75
2022-07-20 12:47:35.107     75
2022-07-20 12:51:01.370     75
2022-07-20 12:52:32.433     75
2022-07-20 12:55:19.240     75
2022-07-20 12:56:43.793     75
2022-07-20 12:58:09.890     75
2022-07-20 12:59:30.660     75
2022-07-20 13:00:51.493     75
2022-07-20 13:02:12.290     75
2022-07-20 13:03:34.977     75
2022-07-20 13:04:55.207     75
2022-07-20 13:06:16.070     75
2022-07-20 13:07:44.260     75
2022-07-20 13:09:04.610     75
2022-07-20 13:10:31.490     75
2022-07-20 13:16:50.060     75
2022-07-20 13:18:22.540     75
2022-07-20 13:20:08.420     75
2022-07-20 13:21:24.263     75
2022-07-20 13:22:54.507     75
2022-07-20 13:24:16.277     75
2022-07-20 13:25:34.363     75
2022-07-20 13:27:52.450     85
2022-07-20 13:29:27.670     85
2022-07-20 13:30:57.497     85
2022-07-20 13:33:51.703     85
2022-07-20 13:35:18.760     85
2022-07-20 13:36:46.613     85
2022-07-20 13:38:12.270     85
2022-07-20 13:39:39.317     85
2022-07-20 13:41:17.830     85
2022-07-20 13:42:34.783     85
2022-07-20 13:44:07.710     85
2022-07-20 13:45:37.210     85
2022-07-20 13:47:04.050     85
2022-07-20 13:48:24.860     85
2022-07-20 13:50:00.310     85
2022-07-20 13:51:21.963     85
2022-07-20 13:53:10.090     85
2022-07-20 13:54:33.530     85
2022-07-20 13:55:54.050     85
2022-07-20 13:57:18.107     85
2022-07-20 13:58:58.043     85
2022-07-20 14:00:17.117     85
2022-07-20 14:01:40.283     85
2022-07-20 14:03:09.720     85
2022-07-20 14:05:20.477     85
2022-07-20 14:07:15.293     85
2022-07-20 14:08:50.077     85
2022-07-20 14:10:22.320     85
2022-07-20 14:12:05.843     85

To complicate things more, I am to calculate the target between distinct time blocks.

1 - 6:00 to 7:00
2 - 7:00 to 8:00
3 - 8:15 to 9:00
4 - 9:00 to 10:00
5 - 10:15 to 11:00
6 - 11:00 to 12:00
7 - 12:30 to 13:30
8 - 13:30 to 14:30
9 - 14:45 to 15:30
10 - 15:30 to 16:30

Calculation Example From Block 6.

I am leaving the decimal point in place until I am told whether to round up or down.

11:00:00 - 11:46:34 Ran 23 units      
- Run Time 2794s / 98s Takt Time = 28.52 Units Should Have Been Produced  

11:46:34 - 12:00:00 Ran 2 units     
- Run Time 806s / 75s Takt Time = 10.74 Units Should Have Been Produced 

- Target For Block 6 = 39.26 Units 

Expected Result *Corrected Group 7 & 8

TimeBlock       Target
----------------------
1               36.73
2               36.73
3               27.55
4               36.73
5               27.55
6               39.25
7               47.58
8               42.35
9               0
10              0

I have a stored procedure already that gets the total produced per time block, average actual cycle time between entries, and calculates performance based on actual cycle time vs target. However, I am having a hard time visualizing a way to do this in SQL.

CodePudding user response:

I hope you have the time block information in a table. You can then join to it and make the grouping easier.

The query uses window function lead() or lag() to group those rows with same TaktTime together as a group Grp

After Grp information is available, next is to get the first ProducedDT and last ProducedDT of the group to calculate the datediff() in seconds. However, for your requirement, it is not simply that way. It might be the start or end time of the time block. That is what the CTE cte is doing. start_tm and end_tm is the start and end time used for calculation

CTE pl consists of other value of the Produced Date & Time to make subsequent calculation and comparison of date and time easier. ProducedD is converted back to datetime instead of just date to save some typing futher on when need to add a date and a time together.

The solution is based on following table schema.

create table productionLog 
(
    ProducedDT  datetime,
    TaktTime    int
);

create table time_block
(
    id          int,
    time_start  time(0),
    time_end    time(0)
);

The query

with pl as
(
    select  ProducedDT, 
            ProducedD = convert(datetime, convert(date, ProducedDT)),
            ProducedT = convert(time(0), ProducedDT),
            TaktTime, 
            g   = case  when TaktTime
                        <>   lag(TaktTime) over (order by ProducedDT)
                        then 1
                        else 0
                        end
    from    productionLog 
),
cte as
(
    select  *,
            start_tm    = coalesce(lag(ProducedDT) over (partition by pl.ProducedD, tb.id
                                                             order by pl.ProducedDT),
                                   pl.ProducedD   convert(datetime, tb.time_start)),
            end_tm      = case  when lead(ProducedDT) over (partition by pl.ProducedD, tb.id
                                                                order by pl.ProducedDT) is not null
                                then ProducedDT
                                else pl.ProducedD   convert(datetime, tb.time_end)
                                end
    from    (
                select  ProducedDT, ProducedD, ProducedT, TaktTime,
                        Grp = sum(g) over (order by ProducedDT)
                from    pl
            ) pl
            inner join time_block tb    on  tb.time_start   <= pl.ProducedT
                                       and  tb.time_end >  pl.ProducedT
)
select  ProducedD, id, sum(Diff * 1.0 / TaktTime)
from
(
    select  ProducedD, id, TaktTime, Grp, 
            Diff = datediff(second, min(start_tm), max(end_tm))
    from    cte
    group by ProducedD, id, TaktTime, Grp
) t
group by ProducedD, id;

db<>fiddle demo

  • Related