Querying sequential data with date/time and text values in the same column - sql

My data is single field, and include date, time, hour but also include data that i need.
Already query 2 keyword but the data still big and too many empty second keyword
SELECT Field1
FROM TABLE1
WHERE Field1 Like '*EVENT_1' Or
Field1 Like '*DATETIME'
I expect the output is:
Thanks in advance

Start by importing your log data into Access. While doing so, tell Access to create its own Primary Key, which will be an AutoNumber:
[impLogData]
ID Field1
-- ------------------
1 May/01/2019 7:00
2 EVENT_0
3 EVENT_1 - val:10
4 EVENT_2
5 EVENT_3
6 EVENT_4
7 EVENT_5
8 EVENT_6
9 May/01/2019 8:00
10 EVENT_2
11 EVENT_3
12 EVENT_12
13 EVENT_13
14 EVENT_14
15 May/01/2019 9:00
16 EVENT_0
17 EVENT_1 - val:15
18 EVENT_2
Create a [tblLogTime] table as
ID - Long Integer, Primary Key
logTime - Date/Time
and populate it with
INSERT INTO tblLogTime ( ID, logTime )
SELECT impLogData.ID, CDate([Field1]) AS Expr1
FROM impLogData
WHERE (((IsDate([Field1]))=True));
producing
[tblLogTime]
ID logTime
-- -------------------
1 2019-05-01 07:00:00
9 2019-05-01 08:00:00
15 2019-05-01 09:00:00
Then create a [tblLogEvent] table as
logTime - Date/Time
logEvent - Text(255)
and populate it with
INSERT INTO tblLogEvent ( logTime, logEvent )
SELECT DMax("logTime","tblLogTime","ID < " & [impLogData].[ID]) AS Expr1, impLogData.Field1
FROM impLogData LEFT JOIN tblLogTime ON impLogData.ID = tblLogTime.ID
WHERE (((tblLogTime.ID) Is Null));
producing
[tblLogEvent]
logTime logEvent
------------------- ----------------
2019-05-01 07:00:00 EVENT_0
2019-05-01 07:00:00 EVENT_1 - val:10
2019-05-01 07:00:00 EVENT_2
2019-05-01 07:00:00 EVENT_3
2019-05-01 07:00:00 EVENT_4
2019-05-01 07:00:00 EVENT_5
2019-05-01 07:00:00 EVENT_6
2019-05-01 08:00:00 EVENT_2
2019-05-01 08:00:00 EVENT_3
2019-05-01 08:00:00 EVENT_12
2019-05-01 08:00:00 EVENT_13
2019-05-01 08:00:00 EVENT_14
2019-05-01 09:00:00 EVENT_0
2019-05-01 09:00:00 EVENT_1 - val:15
2019-05-01 09:00:00 EVENT_2
You can then select EVENT_1 rows using
SELECT tblLogEvent.logTime, tblLogEvent.logEvent
FROM tblLogEvent
WHERE (((tblLogEvent.logEvent) Like "EVENT_1 *"))
ORDER BY tblLogEvent.logTime;
producing
logTime logEvent
------------------- ----------------
2019-05-01 07:00:00 EVENT_1 - val:10
2019-05-01 09:00:00 EVENT_1 - val:15

Related

Calculate difference between endTime from ID 1 and startTime from ID 2

id startTime endTime
1 2022-12-3 13:00:00 2022-12-3 14:00:00
2 2022-12-3 14:00:00 2022-12-3 14:30:00
3 2022-12-3 15:00:00 2022-12-3 15:15:00
4 2022-12-3 15:30:00 2222-12-3 16:30:00
5 2022-12-3 18:30:00 2022-12-3 19:00:00
SELECT startTime, endTime,
(TIMESTAMPDIFF(MINUTE, startTime , endTime) = '60') AS MinuteDiff
FROM booking
OUTPUT:
id startTime endTime MinuteDiff
1 2022-12-3 13:00:00 2022-12-3 14:00:00 1
2 2022-12-3 14:00:00 2022-12-3 14:30:00 0
3 2022-12-3 15:00:00 2022-12-3 15:15:00 0
4 2022-12-3 15:30:00 2022-12-3 16:30:00 1
5 2022-12-3 18:30:00 2022-12-3 19:00:00 0
I am calculating the difference between the startTime and endTime of ID 1, how to calculate the difference between the endTime of ID 1 and the startTime of ID 2, and so on?
Do try this one:
If you want your last row to be included in your result, use LEFT JOIN, if you don't want to include the last row use 'JOIN'.
SELECT d.`id`,
d.`endTime`,
IFNULL(d1.`startTime`,d.`endTime`),
IFNULL(TIMESTAMPDIFF(MINUTE, d.endTime, d1.startTime),0) FROM date_table d LEFT
JOIN date_table d1 ON d1.`id`=d.`id`+1
Or you can use following with Windows Functions:
SELECT
id,
endTime,
lead(startTime) over (order by id) nextStartDate,
TIMESTAMPDIFF(MINUTE,endTime,lead(startTime) over (order by id)) as timeDiff
FROM
date_table d;

SQL query to select the start and end datetime of a value with system versioned tables

Basically, I want to use system versioned tables to find out the start and end date all users held a position within a company.
I'm struggling with the amount of other changes made to the record (Other field changes that create a new versioned record).
I originally tried to Group By UserId, CompanyId, Position and then take the min SysStartTime and max SysEndTime. Which at first glance did work. However it does not work if a position is changed back to its original value.
SELECT DISTINCT
cu.UserId,
cu.CompanyId,
cu.Position,
MIN(cu.SysStartTime) AS StartTime,
MAX(cu.SysEndTime) AS EndTime
FROM dbo.CompanyUser FOR SYSTEM_TIME ALL cu
GROUP BY cu.UserId, cu.CompanyId, cu.Position
Focusing on UserId 1, they were an 'Assistant', then a 'Manager', then back to an 'Assistant' again. I want to get the start and end date of each of these positions reguardless of how many Other changes are made between positions.
UserId CompanyId Position Other SysStartTime SysEndTime
-------- ----------- ----------- ------- ---------------------- ---------------------
1 1 Assistant A 2019-12-01 13:00:00 2019-12-01 14:00:00
2 1 Manager A 2019-12-01 13:00:00 2019-12-01 20:00:00
1 1 Assistant B 2019-12-01 14:00:00 2019-12-01 17:00:00
1 1 Manager A 2019-12-01 17:00:00 2019-12-01 20:00:00
2 1 Executive A 2019-12-01 20:00:00 9999-12-31 23:59:59
3 1 CEO A 2019-12-01 13:00:00 9999-12-31 23:59:59
1 1 Assistant A 2019-12-01 20:00:00 9999-12-31 23:59:59
I want a query that will return the following:
UserId CompanyId Position SysStartTime SysEndTime
-------- ----------- ----------- ---------------------- ---------------------
1 1 Assistant 2019-12-01 13:00:00 2019-12-01 17:00:00
2 1 Manager 2019-12-01 13:00:00 2019-12-01 20:00:00
1 1 Manager 2019-12-01 17:00:00 2019-12-01 20:00:00
2 1 Executive 2019-12-01 20:00:00 9999-12-31 23:59:59
3 1 CEO 2019-12-01 13:00:00 9999-12-31 23:59:59
1 1 Assistant 2019-12-01 20:00:00 9999-12-31 23:59:59
Thanks
This should do what you need (Fiddle).
WITH T
AS (SELECT *,
LAG(Position) OVER (PARTITION BY UserId ORDER BY SysStartTime) AS PrevPosition
FROM dbo.CompanyUser FOR SYSTEM_TIME ALL cu)
SELECT UserId,
CompanyId,
Position,
Other,
SysStartTime,
SysEndTime = LEAD(SysStartTime, 1, SysEndTime) OVER (PARTITION BY UserId ORDER BY SysStartTime)
FROM T
WHERE EXISTS (SELECT PrevPosition
EXCEPT
SELECT Position)
ORDER BY UserId,
SysStartTime
You should use LAG to achieve this.
SELECT UserId, CompanyId, Position, StartTime, EndTime
FROM
(
SELECT DISTINCT
cu.UserId,
cu.CompanyId,
cu.Position,
LAG(cu.Position) OVER(PARTITION BY cu.UserId,cu.Position ORDER BY (SELECT NULL)) NextPosition
MIN(cu.SysStartTime) AS StartTime,
MAX(cu.SysEndTime) AS EndTime
FROM dbo.CompanyUser FOR SYSTEM_TIME ALL cu
GROUP BY cu.UserId, cu.CompanyId, cu.Position
)T
WHERE Position <> ISNULL(NextPosition,'')
Result
UserId CompanyId Position SysStartTime SysEndTime
-------- ----------- ----------- ---------------------- ---------------------
1 1 Assistant 2019-12-01 13:00:00 2019-12-01 17:00:00
2 1 Manager 2019-12-01 13:00:00 2019-12-01 20:00:00
1 1 Manager 2019-12-01 17:00:00 2019-12-01 20:00:00
2 1 Executive 2019-12-01 20:00:00 9999-12-31 23:59:59
3 1 CEO 2019-12-01 13:00:00 9999-12-31 23:59:59
1 1 Assistant 2019-12-01 20:00:00 9999-12-31 23:59:59

SQL Collapse Data

I am trying to collapse data that is in a sequence sorted by date. While grouping on the person and the type.
The data is stored in an SQL server and looks like the following -
seq person date type
--- ------ ------------------- ----
1 1 2018-02-10 08:00:00 1
2 1 2018-02-11 08:00:00 1
3 1 2018-02-12 08:00:00 1
4 1 2018-02-14 16:00:00 1
5 1 2018-02-15 16:00:00 1
6 1 2018-02-16 16:00:00 1
7 1 2018-02-20 08:00:00 2
8 1 2018-02-21 08:00:00 2
9 1 2018-02-22 08:00:00 2
10 1 2018-02-23 08:00:00 1
11 1 2018-02-24 08:00:00 1
12 1 2018-02-25 08:00:00 2
13 2 2018-02-10 08:00:00 1
14 2 2018-02-11 08:00:00 1
15 2 2018-02-12 08:00:00 1
16 2 2018-02-14 16:00:00 3
17 2 2018-02-15 16:00:00 3
18 2 2018-02-16 16:00:00 3
This data set contains about 1.2 million records that resemble the above.
The result that I would like to get from this would be -
person start type
------ ------------------- ----
1 2018-02-10 08:00:00 1
1 2018-02-20 08:00:00 2
1 2018-02-23 08:00:00 1
1 2018-02-25 08:00:00 2
2 2018-02-10 08:00:00 1
2 2018-02-14 16:00:00 3
I have the data in the first format by running the following query -
select
ROW_NUMBER() OVER (ORDER BY date) AS seq
person,
date,
type,
from table
group by person, date, type
I am just not sure how to keep the minimum date with the other distinct values from person and type.
This is a gaps-and-islands problem so, you can use differences of row_number() & use them in grouping :
select person, min(date) as start, type
from (select *,
row_number() over (partition by person order by seq) seq1,
row_number() over (partition by person, type order by seq) seq2
from table
) t
group by person, type, (seq1 - seq2)
order by person, start;
The correct solution using the difference of row numbers is:
select person, type, min(date) as start
from (select t.*,
row_number() over (partition by person order by seq) as seqnum_p,
row_number() over (partition by person, type order by seq) as seqnum_pt
from t
) t
group by person, type, (seqnum_p - seqnum_pt)
order by person, start;
type needs to be included in the GROUP BY.

Total time calculation in a sql query for a day where time in 24 hour format as hhmm

I have a table with date(date), left time(varchar2(4)) and arrival time(varchar2(4)). Time taken is in 24 hour format as hhmm. If a person travel 3 times a day, what will be the query to calculate total travel time in a day?
I am using oracle 11g. Kindly help. Thank you.
Convert the value to a number and report in minutes:
select to_number(substring(time, 1, 2))*60 + to_number(substring(time, 3, 2)) as minutes
Your query would look something like:
select person, sum(to_number(substring(time, 1, 2))*60 + to_number(substring(time, 3, 2))) as minutes
from t
group by person;
I see no reason to convert this back to a string -- or to even store the value as a string instead of as a number. But if you need to, you can reverse the process to get a string.
There are 2 answers, If you want to sum time only on date then it can be done as:-
select curr_date,
sum(24 * (to_date(arrival_time, 'HH24:mi:ss')- to_date(left_time, 'HH24:mi:ss'))) as difference
from sql_prac group by curr_date,arrival_time,left_time;
The sample output is as follows:-
select curr_date,left_time,arrival_time from sql_prac;
CURR_DATE LEFT_TIME ARRIVAL_TIME
--------- -------------------- --------------------
30-JUN-17 00:00:00 15:00:00
30-JUL-17 03:30:00 11:30:00
30-AUG-17 03:00:00 12:30:00
30-SEP-17 04:00:00 17:00:00
30-JUN-17 00:00:00 15:00:00
30-JUL-17 03:30:00 11:30:00
30-AUG-17 03:00:00 12:30:00
30-SEP-17 04:00:00 17:00:00
30-SEP-17 04:00:00 17:00:00
9 rows selected
select curr_date,sum(24 * (to_date(arrival_time, 'HH24:mi:ss')- to_date(left_time, 'HH24:mi:ss'))) as difference
from sql_prac group by curr_date,arrival_time,left_time;
CURR_DATE DIFFERENCE
--------- ----------
30-JUN-17 30
30-JUL-17 16
30-SEP-17 39
30-AUG-17 19
If you want to sum it by person and date then it can be done as:-
select dept,curr_date,sum(24 * (to_date(arrival_time, 'HH24:mi:ss')- to_date(left_time, 'HH24:mi:ss'))) as difference
from sql_prac group by dept,curr_date,arrival_time,left_time order by Dept;
The sample output is as follows:-
Data in table is:-
select dept,curr_date,left_time,arrival_time from sql_prac;
DEPT CURR_DATE LEFT_TIME ARRIVAL_TIME
-------------------- --------- -------------------- --------------------
A 30-SEP-17 04:00:00 17:00:00
B 30-SEP-17 04:00:00 17:00:00
C 30-AUG-17 03:00:00 12:30:00
D 30-DEC-17 04:00:00 17:00:00
A 30-SEP-17 04:00:00 17:00:00
B 30-JUL-17 03:30:00 11:30:00
C 30-AUG-17 03:00:00 12:30:00
D 30-SEP-17 04:00:00 17:00:00
R 30-SEP-17 04:00:00 17:00:00
Data fetched using the query
select dept,curr_date,sum(24 * (to_date(arrival_time, 'HH24:mi:ss')- to_date(left_time, 'HH24:mi:ss'))) as difference
from sql_prac group by dept,curr_date,arrival_time,left_time order by Dept;
DEPT CURR_DATE DIFFERENCE
-------------------- --------- ----------
A 30-SEP-17 26
B 30-JUL-17 8
B 30-SEP-17 13
C 30-AUG-17 19
D 30-SEP-17 13
D 30-DEC-17 13
R 30-SEP-17 13

Select all table in 2 table with null value

I Have 2 Table in SQL SERVER 2005:
first table :
Tanggal
2015/01/01
2015/01/02
2015/01/03
2015/01/04
2015/01/05
2015/01/06
Second Table :
Tanggal Jam_Masuk Jam_Pulang. Id_user
2015/01/01 08:00:00 17:00:00 00600320
2015/01/03 08:00:00 17:00:00 00600320
2015/01/05 08:00:00 17:00:00 00600320
2015/01/06 08:00:00 17:00:00 00600320
I want select like this :
Tanggal Jam_Masuk Jam_Pulang Total Status Id_user
2015/01/01 08:00:00 17:00:00 09:00:00 OK 00600320
2015/01/02 --:--:-- --:--:-- --:--:-- ALPHA/IZIN 00600320
2015/01/03 08:00:00 17:00:00 09:00:00 OK 00600320
2015/01/04 --:--:-- --:-- :-- --:--:-- ALPHA/IZIN 00600320
2015/01/05 08:00:00 17:00:00 09:00:00 OK 00600320
2015/01/06 08:00:00 17:00:00 09:00:00 OK 00600320
Note : Field Total (hh:mm:ss)= Jam_Pulang - Jam_Masuk
Thanks Before
LEFT JOIN the two tables, Use a CASE statement for the Status and use the DATEDIFF function for the total. Also use CONVERT for the datestamp Tanggal with style 111 for your expected output of YYYY/MM/DD.
SELECT CONVERT(VARCHAR(50),a.Tanggal,111) AS Tanggal,
b.Jam_Masuk,
b.Jam_Pulang,
DATEDIFF(hour, Jam_Masuk, Jam_Pulang) AS Total,
b.Id_user,
CASE WHEN b.Id_user IS NOT NULL THEN 'OK' ELSE NULL END AS Status
FROM tab1 a
LEFT JOIN tab12 b ON a.Tanggal = b.Tanggal
OUTPUT
Tanggal Jam_Masuk Jam_Pulang Total Id_user Status
2015/01/01 08:00:00 17:00:00 9 600320 OK
2015/01/02 (null) (null) (null) (null) (null)
2015/01/03 08:00:00 17:00:00 9 600320 OK
2015/01/04 (null) (null) (null) (null) (null)
2015/01/05 08:00:00 17:00:00 9 600320 OK
2015/01/06 08:00:00 17:00:00 9 600320 OK