change the output - sql

Sorry I am new to sql world could this statement be checkin time different with checkout time and remove checkinorout from the statement as you well see :
SELECT
USERINFO.Badgenumber AS USERID,
CHECKINOUT.CHECKTIME AS Checkin,
CHECKINOUT.CHECKTIME AS Checkout,
Machines.MachineAlias,
CHECKINOUT.checkinorout
FROM CHECKINOUT
INNER JOIN USERINFO ON CHECKINOUT.USERID = USERINFO.USERID
INNER JOIN Machines ON CHECKINOUT.SENSORID = Machines.MachineNumber
WHERE (CHECKINOUT.CHECKTIME > '2014-09-25 00:00:00.000')
order by checkin
Output:
USERID Checkin Checkout Machines checkinorout
32 2014-09-25 09:12:57.000 2014-09-25 09:12:57.000 HQ Checkin
32 2014-09-25 12:58:51.000 2014-09-25 12:58:51.000 HQ CheckOut
32 2014-09-26 18:03:33.000 2014-09-26 18:03:33.000 HQ Checkin
32 2014-09-26 22:03:11.000 2014-09-26 22:03:11.000 HQ CheckOut
32 2014-09-27 12:57:55.000 2014-09-27 12:57:55.000 HQ Checkin
32 2014-09-27 17:01:32.000 2014-09-27 17:01:32.000 HQ CheckOut
32 2014-09-28 13:05:03.000 2014-09-28 13:05:03.000 HQ Checkin
32 2014-09-28 17:35:29.000 2014-09-28 17:35:29.000 HQ CheckOut
32 2014-09-29 09:18:12.000 2014-09-29 09:18:12.000 HQ Checkin
32 2014-09-29 18:10:43.000 2014-09-29 18:10:43.000 HQ CheckOut
32 2014-09-30 09:12:13.000 2014-09-30 09:12:13.000 HQ Checkin
I need the output be like this
USERID Checkin Checkout Machines
32 2014-09-25 09:12:57.000 2014-09-25 12:58:51.000 HQ
32 2014-09-26 18:03:33.000 2014-09-26 22:03:11.000 HQ
32 2014-09-27 12:57:55.000 2014-09-27 17:01:32.000 HQ
32 2014-09-28 13:05:03.000 2014-09-28 17:35:29.000 HQ
32 2014-09-29 09:18:12.000 2014-09-29 18:10:43.000 HQ
Thanks MR #sgeddes but when i edit your statement to have a result
with cte as (
select *,
row_number() over (partition by userid, checkinorout order by CHECKTIME) rn
from CHECKINOUT
)
select userid,
max(case when checkinorout = 'checkin' then CHECKTIME end) checkin,
max(case when checkinorout = 'checkout' then CHECKTIME end) checkout
from cte where USERID=15 and CHECKTIME between '2014-9-21 00:00:00.000' and '2014-10-25 00:00:00.000'
group by userid , rn
userid checkin checkout
15 NULL 2014-09-21 18:50:24.000
15 NULL 2014-09-22 18:06:15.000
15 NULL 2014-09-23 18:01:30.000
15 NULL 2014-09-24 16:52:36.000
15 NULL 2014-09-25 12:58:51.000
15 NULL 2014-09-26 22:03:11.000
15 NULL 2014-09-27 17:01:32.000
15 NULL 2014-09-28 17:35:29.000
15 NULL 2014-09-29 18:10:43.000
15 NULL 2014-09-30 18:11:19.000
15 NULL 2014-10-01 17:52:49.000
15 NULL 2014-10-12 20:13:10.000
15 2014-09-21 10:17:24.000 2014-10-13 22:13:11.000
15 2014-09-22 09:18:29.000 2014-10-14 21:49:28.000
15 2014-09-23 09:10:15.000 2014-10-15 10:14:09.000
15 2014-09-24 09:43:27.000 2014-10-16 17:55:06.000
15 2014-09-25 09:12:57.000 2014-10-17 23:17:00.000
15 2014-09-26 18:03:33.000 2014-10-20 12:38:22.000
15 2014-09-27 12:57:55.000 2014-10-21 07:31:39.000
15 2014-09-28 13:05:03.000 2014-10-22 05:51:47.000
15 2014-09-29 09:18:12.000 2014-10-24 11:26:06.000
15 2014-09-30 09:12:13.000 NULL
15 2014-10-01 10:16:59.000 NULL
15 2014-10-02 10:13:52.000 NULL
15 2014-10-03 00:59:18.000 NULL
15 2014-10-11 22:07:06.000 NULL
15 2014-10-12 09:58:34.000 NULL
15 2014-10-13 05:09:34.000 NULL
15 2014-10-14 11:42:58.000 NULL
15 2014-10-15 04:48:27.000 NULL
15 2014-10-15 15:49:06.000 NULL
15 2014-10-16 09:14:21.000 NULL
15 2014-10-16 21:14:18.000 NULL
15 2014-10-17 00:59:57.000 NULL
15 2014-10-18 17:42:26.000 NULL
15 2014-10-20 01:22:01.000 NULL
15 2014-10-21 01:24:30.000 NULL
15 2014-10-22 00:10:34.000 NULL
15 2014-10-23 20:01:02.000 NULL
15 2014-10-24 01:08:51.000 NULL
and i need it to be
userid checkin checkout
15 2014-09-21 10:17:24.000 2014-09-21 18:50:24.000
15 2014-09-22 09:18:29.000 2014-09-22 18:06:15.000
15 2014-09-23 09:10:15.000 2014-09-23 18:01:30.000
15 2014-09-24 09:43:27.000 2014-09-24 16:52:36.000
15 2014-09-25 09:12:57.000 2014-09-25 12:58:51.000
15 2014-09-26 18:03:33.000 2014-09-26 22:03:11.000
15 2014-09-27 12:57:55.000 2014-09-27 17:01:32.000
Thanks Mr #slavoo
what i have when i try ....
SELECT
u.Badgenumber AS USERID,
c.CHECKTIME AS Checkout,
checkingOut.time AS Checkin,
m.MachineAlias
FROM CHECKINOUT c
INNER JOIN USERINFO u ON c.USERID = u.USERID
INNER JOIN Machines m ON c.SENSORID = m.MachineNumber
OUTER APPLY
(
SELECT top 1 c2.CHECKTIME as time FROM CHECKINOUT c2
WHERE c2.checkinorout = 'Checkout'
AND c.USERID = c2.USERID
AND c.SENSORID = c2.SENSORID
AND c.CHECKTIME < c2.CHECKTIME
order by c2.CHECKTIME asc
) as checkingOut
WHERE (c.CHECKTIME between '2014-10-19 00:00:00.000' and '2014-10-27 00:00:00.000' )
and u.Badgenumber=660
AND c.checkinorout = 'Checkin'
AND checkingOut.time is not null
order by checkingOut.time
The output:
USERID Checkout Checkin MachineAlias
660 2014-10-19 01:56:47.000 2014-10-19 17:27:41.000 Branch4
660 2014-10-20 02:00:14.000 2014-10-20 17:39:35.000 Branch4
660 2014-10-21 01:55:49.000 2014-10-21 16:57:22.000 Branch4
660 2014-10-22 01:59:23.000 2014-10-25 16:48:29.000 Branch4
660 2014-10-23 16:59:34.000 2014-10-25 16:48:29.000 Branch4
660 2014-10-24 16:58:36.000 2014-10-25 16:48:29.000 Branch4
660 2014-10-25 01:56:47.000 2014-10-25 16:48:29.000 Branch4
and i need it to be
USERID Checkout Checkin MachineAlias
660 2014-10-20 02:00:14.000 2014-10-19 17:27:41.000 Branch4
660 2014-10-21 01:55:49.000 2014-10-20 17:39:35.000 Branch4
660 2014-10-22 01:59:23.000 2014-10-21 16:57:22.000 Branch4
660 Null 2014-10-23 16:59:34.000 Branch4
660 2014-10-25 01:56:47.000 2014-10-24 16:58:36.000 Branch4
660 2014-10-26 00:55:35.000 2014-10-25 16:48:29.000 Branch4
and this is the table i read from it
select USERID ,CHECKTIME,checkinorout from CHECKINOUT where USERID=80 and CHECKTIME between '2014-10-19 00:00:00.000' and '2014-10-27 00:00:00.000'
order by CHECKTIME
and this is the full transaction for this user
80 2014-10-19 01:56:47.000 Checkin
80 2014-10-19 17:27:41.000 CheckOut
80 2014-10-20 02:00:14.000 Checkin
80 2014-10-20 17:39:35.000 CheckOut
80 2014-10-21 01:55:49.000 Checkin
80 2014-10-21 16:57:22.000 CheckOut
80 2014-10-22 01:59:23.000 Checkin
80 2014-10-23 16:59:34.000 Checkin
80 2014-10-24 16:58:36.000 Checkin
80 2014-10-25 01:56:47.000 Checkin
80 2014-10-25 16:48:29.000 CheckOut
80 2014-10-26 00:55:35.000 Checkin
for your note i have script its update the check in or out in checkinorout column
to know this report be finger print check in and check out report
and if he found no check in leave it Null and if he found the check out null leave it null ( this employ have shift check in 5:00:00 pm and check out 2:00:00 am ) ; .

SELECT
u.Badgenumber AS USERID,
c.CHECKTIME AS Checkin,
checkingOut.time AS Checkout,
m.MachineAlias
FROM CHECKINOUT c
INNER JOIN users u ON c.USERID = u.USERID
INNER JOIN Machines m ON c.SENSORID = m.MachineNumber
OUTER APPLY
(
SELECT top 1 c2.CHECKTIME as time FROM CHECKINOUT c2
WHERE c2.checkinorout = 'Checkout'
AND c.USERID = c2.USERID
AND c.SENSORID = c2.SENSORID
AND c.CHECKTIME < c2.CHECKTIME
AND CAST(c.CHECKTIME as DATE) = CAST(c2.CHECKTIME as DATE)
order by c2.CHECKTIME asc
) as checkingOut
WHERE (c.CHECKTIME > '2014-09-25 00:00:00.000')
AND c.checkinorout = 'Checkin'
order by checkin
SQL Fiddle
SQL Fiddle after update
Or this:
SELECT
u.Badgenumber AS USERID,
c.CHECKTIME AS Checkin,
checkingOut.time AS Checkout,
Machines.MachineAlias
FROM CHECKINOUT c
INNER JOIN users u ON c.USERID = u.USERID
INNER JOIN Machines ON c.SENSORID = Machines.MachineNumber
OUTER APPLY
(
SELECT top 1 c2.CHECKTIME as time FROM CHECKINOUT c2
WHERE c2.checkinorout = 'Checkout'
AND c.USERID = c2.USERID
AND c.SENSORID = c2.SENSORID
AND c.CHECKTIME < c2.CHECKTIME
AND NOT EXISTS (SELECT * FROM CHECKINOUT c3
WHERE c3.checkinorout = 'Checkin'
AND c3.USERID = c2.USERID
AND c3.SENSORID = c2.SENSORID
AND c3.CHECKTIME > c.CHECKTIME
AND c3.CHECKTIME < c2.CHECKTIME)
order by c2.CHECKTIME asc
) as checkingOut
WHERE (c.CHECKTIME > '2014-09-25 00:00:00.000')
AND c.checkinorout = 'Checkin'
order by checkin
SqlFiddle

You can use ROW_NUMBER() to establish a grouping between your checkins and checkouts. Then you need to pivot your results -- you can use MAX with CASE to do that:
Here's a simplified version using a common table expression:
with cte as (
select *,
row_number() over (partition by userid, checkinorout order by checkin) rn
from results
)
select userid,
max(case when checkinorout = 'checkin' then checkin end) checkin,
max(case when checkinorout = 'checkout' then checkout end) checkout,
machines
from cte
group by userid, machines, rn
SQL Fiddle Demo
Edit, given your comments, can you not just use a HAVING clause to remove the NULL records?
having max(case when checkinorout = 'checkin' then checkin end) is not null
and max(case when checkinorout = 'checkout' then checkout end) is not null
Updated Fiddle

Related

First and last record of a date in SQL Server

I want to generate a user login report where I want to show the users first login time and last logout time for each day of a month. The table of UserLoginSession is as below
UserLoginSessionId
UserId
LoginDate
LogoutDate
1310582
59
2021-04-30 15:49:54.997
2021-04-30 17:31:18.833
1310579
59
2021-04-30 14:53:51.460
NULL
1310575
59
2021-04-30 14:39:45.937
2021-04-30 14:52:23.150
1310569
59
2021-04-30 13:49:36.137
NULL
1300484
59
2021-04-28 15:17:48.837
NULL
1300478
59
2021-04-28 12:17:50.200
NULL
1300466
59
2021-04-28 04:23:48.697
2021-04-28 07:45:11.937
1299527
2466
2021-04-18 06:07:51.070
NULL
1299489
2466
2021-04-17 06:57:01.860
2021-04-17 06:57:28.260
1299449
2466
2021-04-16 10:16:54.730
NULL
1299442
2466
2021-04-16 10:08:30.187
2021-04-16 10:36:05.963
1299422
2466
2021-04-16 07:30:32.990
2021-04-16 10:15:25.777
The output report should be like below where if the logout date is null, it should take the end time of the day
UserId
LoginDate
LogoutDate
59
2021-04-30 13:49:36.137
2021-04-30 17:31:18.833
59
2021-04-28 04:23:48.697
2021-04-28 23:59:59.000
2466
2021-04-18 06:07:51.070
2021-04-18 23:59:59.000
2466
2021-04-17 06:57:01.860
2021-04-17 06:57:28.260
2466
2021-04-16 07:30:32.990
2021-04-16 23:59:59.000
I have tried the below query but it is giving me output in separate rows.
select UserId, case when rn1 = 1 then LoginDate end as [LoginDate], case when rn2 = 1 then LogoutDate end as [LogoutDate]
from (
select
row_number() over (partition by U.UserId, convert(date,s.LoginDate) order by s.LoginDate) as rn1,
row_number() over (partition by U.UserId, convert(date,s.LogoutDate) order by s.LogoutDate desc) as rn2,
S.*
from UserLoginSession S
where S.CreatedAt between #StartDate and #EndDate
) as SubQueryTable
where rn1 = 1 or rn2 = 1
I am not able to bring both the records in a single row in the query. How can I modify my query to achieve the desired result?
Using MIN and MAX and hacking around when LogoutDate is NULL:
SELECT UserId, CONVERT(date, LoginDate), MIN(LoginDate), ISNULL(MAX(LogoutDate), DATEADD(MS, -2, CONVERT(DATETIME,DATEADD(D, 1, CONVERT(date, LoginDate)))))
FROM UserLoginSession
GROUP BY UserId,CONVERT(date, LoginDate)
ORDER BY UserId,CONVERT(date, LoginDate)

Following Start and End Date Columns

I have start and end date columns, and there are some where the start date equals the end date of the previous row without a gap. I'm trying to get it so that it would basically go from the Start Date row who's End Date is null and kinda "zig-zag" up going until the Start Date does not match the End Date.
I've tried CTEs, and ROW_NUMBER() OVER().
START_DTE END_DTE
2018-01-17 2018-01-19
2018-01-26 2018-02-22
2018-02-22 2018-08-24
2018-08-24 2018-09-24
2018-09-24 NULL
Expected:
START_DTE END_DTE
2018-01-26 2018-09-24
EDIT
Using a proposed solution with an added CTE to ensure dates don't have times with them.
WITH
CTE_TABLE_NAME AS
(
SELECT
ID_NUM,
CONVERT(DATE,START_DTE) START_DTE,
CONVERT(DATE,END_DTE) END_DTE
FROM
TABLE_NAME
WHERE ID_NUM = 123
)
select min(start_dte) as start_dte, max(end_dte) as end_dte, grp
from (select t.*,
sum(case when prev_end_dte = end_dte then 0 else 1 end) over (order by start_dte) as grp
from (select t.*,
lag(end_dte) over (order by start_dte) as prev_end_dte
from CTE_TABLE_NAME t
) t
) t
group by grp;
The following query provides these results:
start_dte end_dte grp
2014-08-24 2014-12-19 1
2014-08-31 2014-09-02 2
2014-09-02 2014-09-18 3
2014-09-18 2014-11-03 4
2014-11-18 2014-12-09 5
2014-12-09 2015-01-16 6
2015-01-30 2015-02-02 7
2015-02-02 2015-05-15 8
2015-05-15 2015-07-08 9
2015-07-08 2015-07-09 10
2015-07-09 2015-08-25 11
2015-08-31 2015-09-01 12
2015-10-06 2015-10-29 13
2015-11-10 2015-12-11 14
2015-12-11 2015-12-15 15
2015-12-15 2016-01-20 16
2016-01-29 2016-02-01 17
2016-02-01 2016-03-03 18
2016-03-30 2016-08-29 19
2016-08-30 2016-12-06 20
2017-01-27 2017-02-20 21
2017-02-20 2017-08-15 22
2017-08-15 2017-08-29 23
2017-08-29 2018-01-17 24
2018-01-17 2018-01-19 25
2018-01-26 2018-02-22 26
2018-02-22 2018-08-24 27
2018-08-24 2018-09-24 28
2018-09-24 NULL 29
I tried using having count (*) > 1 as suggested, but it provided no results
Expected example
START_DTE END_DTE
2017-01-27 2018-01-17
2018-01-26 2018-09-24
You can identify where groups of connected rows start by looking for where adjacent rows are not connected. A cumulative sum of these starts then gives you the groups.
select min(start_dte) as start_dte, max(end_dte) as end_dte
from (select t.*,
sum(case when prev_end_dte = start_dte then 0 else 1 end) over (order by start_dte) as grp
from (select t.*,
lag(end_dte) over (order by start_dte) as prev_end_dte
from t
) t
) t
group by grp;
If you want only multiply connected rows (as implied by your question), then add having count(*) > 1 to the outer query.
Here is a db<>fiddle.

My SQL Query is working on one date, but I want start date to end date

I am using SQL Server 2005
I have two tables:
CheckInOut
TR BadgeNum USERID Dated Time CHECKTYPE
------- --------- ------ ----------------------- ----------------------- ----------
2337334 4 1 2018-04-01 00:00:00.000 2018-04-14 10:10:58.000 I
2337334 4 1 2018-04-01 00:00:00.000 2018-04-14 18:10:00.000 O
2337334 4 1 2018-04-02 00:00:00.000 2018-04-14 10:00:10.000 I
2337335 4 1 2018-04-02 00:00:00.000 2018-04-14 18:14:27.000 O
2337336 4 1 2018-04-03 00:00:00.000 2018-04-14 10:22:10.000 I
2337334 4 1 2018-04-03 00:00:00.000 2018-04-14 18:03:11.000 O
2337337 44 5 2018-04-01 00:00:00.000 2018-04-14 09:27:03.000 I
2337337 44 5 2018-04-01 00:00:00.000 2018-04-14 18:27:42.000 O
2337337 44 5 2018-04-02 00:00:00.000 2018-04-14 10:00:50.000 I
2337337 44 5 2018-04-02 00:00:00.000 2018-04-14 18:02:25.000 O
2337337 44 5 2018-04-03 00:00:00.000 2018-04-14 08:58:36.000 I
2337337 44 5 2018-04-03 00:00:00.000 2018-04-14 18:12:18.000 O
UserInfo
Tr UserID BadgeNumber Name
----- ------- ----------- --------------
13652 44 5 SAMIA NAZ
13653 4 1 Waqar Yousufzai
I need to calculate presence hours for each day for each user. My below query is working fine for given day. But I need to calculate for a given range. How do I get expected result?
Select isnull(max(ch.userid), 0)As 'ID'
,isnull(max(ch.badgenum), 0)as 'Badge#'
,isnull(max(convert(Char(10), ch.dated, 103)), '00:00')as 'Date'
,isnull(max(ui.name),'Empty')as 'Name'
,isnull(min(convert(VARCHAR(26), ch.time, 108)), '00:00') as 'Time In'
,case when min(ch.time) = max(ch.time) then '' else isnull(max(convert(VARCHAR(26), ch.time, 108)), '00:00') end as 'TimeOut'
,case when min(ch.time) = max(ch.time) then 'Absent' else 'Present' end as 'Status'
,isnull(CONVERT(varchar(3),DATEDIFF(minute,min(ch.time), max(ch.time))/60) + ' hrs and ' +
RIGHT('0' + CONVERT(varchar(2),DATEDIFF(minute,min(ch.time),max(ch.time))%60),2) + 'Min' , 0) as 'Total Hrs'
From CHECKINOUT ch left Join userinfo ui on ch.badgenum = ui.badgenumber
Where ch.Dated between '2018-04-01' and '2018-04-03' GROUP BY ch.badgenum
Query result
ID Badge# Date Name Time In TimeOut Status Total Hrs
--- ------ ---------- --------------- -------- ---------- -------- -----------------
4 1 03/04/2018 Waqar Yousufzai 11:33:34 18:24:23 Present 30 hrs and 14Min
82 3 03/04/2018 TANVEER ANSARI 09:37:14 19:18:22 Present 32 hrs and 37Min
13 4 03/04/2018 07:19:26 09:30:17 Present 21 hrs and 49Min
44 5 03/04/2018 SAMIA NAZ 08:53:15 18:25:21 Present 33 hrs and 24Min
28 7 03/04/2018 Anees Ahmad 08:34:57 22:00:38 Present 61 hrs and 25Min
46 8 03/04/2018 Shazia - OT 08:10:41 16:15:05 Present 32 hrs and 01Min
Expected result
ID Badge# Date Name Time In TimeOut Status Total Hrs
--- ------ ---------- --------------- -------- ---------- -------- -----------------
4 1 01/04/2018 Waqar Yousufzai 10:30:00 18:00:00 Present 7 hrs and 30Min
4 1 02/04/2018 Waqar Yousufzai 10:30:00 18:00:00 Present 7 hrs and 30Min
4 1 03/04/2018 Waqar Yousufzai 10:00:00 18:00:00 Present 8 hrs and 00Min
44 5 01/04/2018 SAMIA 08:00:00 18:00:00 Present 10 hrs and 00Min
44 5 02/04/2018 SAMIA 08:30:00 18:00:00 Present 9 hrs and 30Min
44 5 03/04/2018 SAMIA 08:00:00 18:00:00 Present 10 hrs and 00Min
You shouldn't do aggregation on date value, it must be part of grouping. Get time out and time in using conditional aggregation. And count total hours worked. Your query should be something like:
select
BadgeNum, USERID, Dated, Name
, right('0' + cast(datediff(mi, [in], [out]) / 60 as varchar(10)), 2) + ':'
+ right('0' + cast(datediff(mi, [in], [out]) % 60 as varchar(10)), 2)
from (
select
ch.BadgeNum, ch.USERID, dated = cast(ch.Dated as date), ui.Name
, [in] = min(case when ch.CHECKTYPE = 'I' then ch.Time end)
, [out] = min(case when ch.CHECKTYPE = 'O' then ch.Time end)
from
CheckInOut ch
left join UserInfo ui on ch.USERID = ui.badgenumber
where
ch.Dated >= '20180401'
and ch.Dated < '20180404'
group by ch.BadgeNum, ch.USERID, cast(ch.Dated as date), ui.Name
) t

SQL: How to get the correct resource time for each time record after removed overlap

I have set of machines used record, and there is more than one work piece used on a machine and sometime each record time period are overlapped. Right now I would get the actual time used on each record after removed overlapped time....but that is difficult to me as a SQL beginner....Hope anyone can give me help...thx
The total used time for CW01 should be 22 hrs and EN01 is 8 hrs after removed ovelap time
Orignal TABLE
operid machine itemid start_time end_time time_used
--------------------------------------------------------------------------------------------------
454 CW01 31 2017-10-16 08:30:00.000 2017-10-16 16:30:00.000 8
456 CW01 33 2017-10-16 13:30:00.000 2017-10-16 18:30:00.000 5
457 CW01 35 2017-10-16 21:30:00.000 2017-10-17 06:30:00.000 9
458 CW01 36 2017-10-16 15:30:00.000 2017-10-16 23:30:00.000 8
460 EN01 70 2017-10-16 08:30:00.000 2017-10-16 10:30:00.000 2
462 EN01 71 2017-10-16 09:30:00.000 2017-10-16 16:30:00.000 7
Desired TABLE
operid machine itemid start_time end_time time_used
--------------------------------------------------------------------------------------------------
454 CW01 31 2017-10-16 08:30:00.000 2017-10-16 16:30:00.000 6.33333
456 CW01 33 2017-10-16 13:30:00.000 2017-10-16 18:30:00.000 2.33333
457 CW01 35 2017-10-16 21:30:00.000 2017-10-17 06:30:00.000 8
458 CW01 36 2017-10-16 15:30:00.000 2017-10-16 23:30:00.000 5.33333
460 EN01 70 2017-10-16 08:30:00.000 2017-10-16 10:30:00.000 1.5
462 EN01 71 2017-10-16 09:30:00.000 2017-10-16 16:30:00.000 6.5
with Q(operid, machine, tm) as(
-- split rows to time points (start(3), end(4), intersect time (1,2))
select distinct A.operid,A.machine,
case N when 1 then (case when A.start_time>B.start_time
then A.start_time else B.start_time end)
when 2 then (case when A.end_time < B.end_time
then A.end_time else B.end_time end)
when 3 then A.start_time
else A.end_time
end
from TabD A
cross join (select 1 N union all select 2 union all select 3 union all select 4) N
left join TabD B
on B.machine=A.machine and B.operid!=A.operid
and B.start_time<A.end_time and B.end_time>A.start_time and N.N in(1,2)
)
select operid, machine, sum(time_len)
from (
select X.operid, A.machine, s_tm, e_tm,
datediff(second, s_tm, e_tm)/3600.0/count(1) time_len
from (
-- join time points to intervals
select operid, machine, tm e_tm,
lag(tm) over(partition by machine,operid order by tm) s_tm
from Q
where Q.tm is not null
) X,
TabD A -- join source rows for interval of time for count it
where s_tm is not null
and A.start_time<X.e_tm and A.end_time>X.s_tm
and A.machine=X.machine
group by X.operid, A.machine, s_tm, e_tm
) Y
group by operid, machine
Example on sqlfiddle.com

SQL: SELECT FROM (SELECT, SELECT)

I receive data from a counter, and I want to create a report that print how much was incremented per hour.
I made this query, but I couldn't do a SELECT from 0 to 23 Hours
SELECT [COLUMN_A],
[COLUMN_B],
[COLUMN_A] - [COLUMN_B] AS TOTAL
FROM (
(SELECT MAX([_Counter]) AS COLUMN_A
FROM [DADOS].[dbo].Table_Producao]
WHERE DatePart(HOUR, _TimeStamp)=9)AS PART_A
CROSS JOIN(SELECT MAX([_Count]) AS COLUMN_B
FROM [DADOS].[dbo].[Table_Producao]
WHERE DatePart(HOUR, _TimeStamp)=8)AS PART_B
)
What a I have:
_TimeStamp _Counter
2015-02-03 14:00:00.000 2
2015-02-03 14:59:00.000 15
2015-02-03 15:00:00.000 17
2015-02-03 15:30:00.000 30
2015-02-03 15:59:00.000 42
2015-02-03 16:00:00.000 43
2015-02-03 16:30:00.000 50
2015-02-03 16:59:00.000 59
2015-02-03 17:00:00.000 61
2015-02-03 17:30:00.000 70
2015-02-03 17:50:00.000 82
2015-02-03 18:00:00.000 86
2015-02-03 18:30:00.000 90
2015-02-03 18:59:00.000 99
2015-02-03 19:00:00.000 102
2015-02-03 19:30:00.000 115
2015-02-03 19:59:00.000 124
2015-02-03 20:00:00.000 126
2015-02-03 20:30:00.000 137
2015-02-03 20:59:00.000 145
2015-02-03 21:00:00.000 147
What I want:
_TimeStamp _Counter
14h 17
15h 27
16h 17
17h 23
18h 17
19h 25
20h 21
21h 2
Any ideas? please
try this.
SELECT Cast(Datepart(hh, [_timestamp]) AS VARCHAR(3))+ 'h',
Sum(_counter)
FROM your_result
GROUP BY Cast(Datepart(hh, [_timestamp]) AS VARCHAR(3))+ 'h',
Cast(_timestamp AS DATE)
I solved my qestion with this query:
WITH QUERY1 AS
(SELECT MAX(_Counter) AS MAX_1, Datepart(hh, [TimeStamp]) AS _TIMESTAMP1
FROM Table
WHERE Cast(DatePart(hh, TimeStamp)AS int) IN (SELECT Cast(Datepart(hh, [TimeStamp]) AS int)
FROM Table
WHERE TimeStamp>=CAST('<%DataQuery%>'+' 00:00:00.000' AS DATETIME) AND TimeStamp<=CAST('<%DataQuery%>'+' 23:59:59.999' AS DATETIME)
)
GROUP BY Cast(Datepart(hh, [TimeStamp])AS int)),
QUERY2 AS
(SELECT MAX(_Counter) AS MAX_2, Datepart(hh, [TimeStamp]) AS _TIMESTAMP2
FROM PLASCAR_DADOS.dbo.Table_Producao
WHERE Cast(DatePart(hh, TimeStamp)AS int) IN (SELECT Cast(Datepart(hh, [TimeStamp]) AS int)+1
FROM Table
WHERE TimeStamp>=CAST('<%DataQuery%>'+' 00:00:00.000' AS DATETIME) AND TimeStamp<=CAST('<%DataQuery%>'+' 23:59:59.999' AS DATETIME)
)
GROUP BY Cast(Datepart(hh, [TimeStamp])AS int))
SELECT _TIMESTAMP1, MAX_2-MAX_1 AS TOTAL
FROM QUERY1 INNER JOIN QUERY2 ON _TIMESTAMP1 =_TIMESTAMP2-1