Reputation: 1225
I am trying to write a query that returns the time taken by an Order from start to completion.
My table looks like below.
Order No. Action DateTime
111 Start 3/23/2018 8:18
111 Complete 3/23/2018 9:18
112 Start 3/24/2018 6:00
112 Complete 3/24/2018 11:10
Now I am trying to calculate the date difference between start and completion of multiple orders and below is my query:
Declare @StartDate VARCHAR(100), @EndDate VARCHAR(100), @Operation VARCHAR(100)
declare @ORDERTable table
(
order varchar(1000)
)
insert into @ORDERTable values ('111')
insert into @ORDERTable values ('112')
Select @Operation='Boiling'
set @EndDate = (SELECT DATE_TIME from PROCESS WHERE ACTION='COMPLETE' AND ORDER in (select order from @ORDERTable) AND OPERATION=@Operation)
---SELECT @EndDate
set @StartDate = (SELECT DATE_TIME from PROCESS WHERE ACTION='START' AND ORDER in (select order from @ORDERTable) AND OPERATION=@Operation)
---SELECT @StartDate
SELECT DATEDIFF(minute, @StartDate, @EndDate) AS Transaction_Time
So, I am able to input multiple orders but I want to get multiple output as well.
And my second question is if I am able to achieve multiple records as output, how am I gonna make sure which datediff is for which Order?
Awaiting for your answers. Thanks in advance.
I am using MSSQL.
Upvotes: 0
Views: 4375
Reputation: 1169
Why don't you attempt to approach this problem with a set-based solution? After all, that's what a RDBMS is for. With an assumption that you'd have orders that are of interest to you in a table variable like you described, @ORDERTable(Order)
, it would go something along the lines of:
SELECT DISTINCT
[Order No.]
, DATEDIFF(
minute,
FIRST_VALUE([DateTime]) OVER (PARTITION BY [Order No.] ORDER BY [DateTime] ASC),
FIRST_VALUE([DateTime]) OVER (PARTITION BY [Order No.] ORDER BY [DateTime] DESC)
) AS Transaction_Time
FROM tableName
WHERE [Order No.] IN (SELECT Order FROM @ORDERTable);
This query works if all the values in the Action
attribute are either Start or Complete, but also if there are others in between them.
To read up more on the FIRST_VALUE()
window function, check out the documentation.
NOTE: works in SQL Server 2012 or newer versions.
Upvotes: 0
Reputation: 94913
You can aggregate by order number and use MAX
or MIN
with CASE WHEN
to get start or end time:
select
order_no,
max(case when action = 'Start' then date_time end) as start_time,
max(case when action = 'Completed' then date_time end) as end_time,
datediff(
minute,
max(case when action = 'Start' then date_time end),
max(case when action = 'Completed' then date_time end)
) as transaction_time
from process
group by order_no
order by order_no;
Upvotes: 1
Reputation: 8324
You can split up your table into two temp tables, cte's, whatever, and then join them together to find the minutes it took to complete
DECLARE @table1 TABLE (OrderNO INT, Action VARCHAR(100), datetime datetime)
INSERT INTO @table1 (OrderNO, Action, datetime)
VALUES
(111 ,'Start' ,'3/23/2018 8:18'),
(111 ,'Complete' ,'3/23/2018 9:18'),
(112 ,'Start' ,'3/24/2018 6:00'),
(112 ,'Complete' ,'3/24/2018 11:10')
;with cte_start AS (
SELECT orderno, Action, datetime
FROM @table1
WHERE Action = 'Start')
, cte_complete AS (
SELECT orderno, Action, datetime
FROM @table1
WHERE Action = 'Complete')
SELECT
start.OrderNO, DATEDIFF(minute, start.datetime, complete.datetime) AS duration
FROM cte_start start
INNER JOIN cte_complete complete
ON start.OrderNO = complete.OrderNO
Upvotes: 1