I have a kusto table where I will receive data every 2 hours. I need to find the start and end time for a given data. Here, endtime should be determined by the system by seeing if the data is not present for that message.
Eg:
Id Name Timestamp
1 A 07-12-2022T04:05:00z
2 A 07-12-2022T06:05:00z
3 A 07-12-2022T08:05:00z
4 A 07-12-2022T12:05:00z
In the above example, we received data at 4,6,8 and it is missing for 10. I need to show that the start time is 04"05"00 and end time as 10:00:00 (here the system should detect and fill-in) and then one more start time as 12:05:00z without and end time as the current time is less than 2 hours from 12:05:00.
let p_max_allowed_gap = 2h;
datatable(Id:int, Name:string, Timestamp:datetime)
[
1 ,"A" ,"2022-07-12T04:05:00z"
,2 ,"A" ,"2022-07-12T06:05:00z"
,3 ,"A" ,"2022-07-12T08:05:00z"
,4 ,"A" ,"2022-07-12T12:05:00z"
]
| partition hint.strategy=native by Name
(
order by Timestamp asc
| extend session_id = row_cumsum(iff(Timestamp - prev(Timestamp) > p_max_allowed_gap, 1, 0))
)
| summarize StartTime = min(Timestamp), EndTime = max(Timestamp) by Name, session_id
| extend EndTime = iff(now() - EndTime < p_max_allowed_gap, datetime(null), EndTime)
Name
session_id
StartTime
EndTime
A
0
2022-07-12T04:05:00Z
2022-07-12T08:05:00Z
A
1
2022-07-12T12:05:00Z
2022-07-12T12:05:00Z
Fiddle
Related
I am trying to subtract timestamp values. It gives ORA-01843: NOT A VALID MONTH error.
Below query runs fine in SQL Devloper,
But while runtime it throws not a valid month error.
I am not able to find out. Can anybody modify this query.
Select substr(TO_TIMESTAMP(TO_CHAR(end_time,'DD-MM-YY HH12:MI:SS'))-(TO_TIMESTAMP(TO_CHAR(start_time,'DD-MM-YY HH12:MI:SS')),12,8))as Duration from Job_execution
If those datatypes are TIMESTAMP, then why don't you just subtract them?
SQL> create table job_execution
2 (id number,
3 start_time timestamp(6),
4 end_time timestamp(6));
Table created.
SQL> insert into job_execution (id, start_time, end_time) values
2 (1, to_timestamp('20.11.2019 10:30:00', 'dd.mm.yyyy hh24:mi:ss'),
3 to_timestamp('25.11.2019 14:00:00', 'dd.mm.yyyy hh24:mi:ss'));
1 row created.
SQL> select end_time - start_time diff from job_execution where id = 1;
DIFF
---------------------------------------------------------------------------
+000000005 03:30:00.000000
SQL>
"Not a valid month" can be result of timestamp values stored into VARCHAR2 columns where you think everything is entered correctly, but there are values such as 25.18.2019 (dd.mm.yyyy), as there's no 18th month in any year.
That's why I asked for the datatype.
[EDIT: how to format the result]
If you want a "nice" displayed result, then it requires some more typing. For example:
SQL> with difference as
2 (select end_time - start_Time as diff
3 from job_execution
4 where id = 1
5 )
6 select extract (day from diff) ||' '||
7 lpad(extract (hour from diff), 2, '0') ||':'||
8 lpad(extract (minute from diff), 2, '0') ||':'||
9 lpad(extract (second from diff), 2, '0') result
10 from difference;
RESULT
--------------------------------------------------------------
5 03:30:00
SQL>
I have a teradata table ABC . I have a column in the table which is of PERIOD data type ( Name of the column is ef_dtm) . I need to update the starting bound of the period column(subtract it by 1 day) whenever starting bound of the period column is '12/31/9999'.
I am using the below query . But it is saying
INVALID Interval Literal.
Can you suggest me an update query?
Nonsequenced validtime
update ABC
set ef_dtm = PERIOD(CAST(end(ef_dtm) as Date) -INTERVAL '-1' DAY , end(ef_dtm))
where begin(ef_dtm) = '12/31/9999'
The error is because of part INTERVAL '-1' DAY
It should be INTERVAL -'1' DAY i.e. minus - outside the '1'
Your query has 2 more problems.
No need to cast period begin to DATE as INTERVAL arithmetic works on TIMESTAMP
DATE literals are wrong. It should be YYYY-MM-DD; Moreover it should be TIMESTAMP corresponding to period column datatype.
Correct query is as below.
nonsequenced validtime
UPDATE ABC
SET ef_dtm = PERIOD(begin(ef_dtm) + INTERVAL -'1' DAY, end(ef_dtm))
WHERE begin(ef_dtm) = TIMESTAMP '1999-12-31 00:00:00.000000';
OR
nonsequenced validtime
UPDATE ABC
SET ef_dtm = PERIOD(begin(ef_dtm) - INTERVAL '1' DAY, end(ef_dtm))
WHERE begin(ef_dtm) = TIMESTAMP '1999-12-31 00:00:00.000000';
DEMO
Create Table:
CREATE TABLE ABC ( ef_dtm period(timestamp(6)) AS validtime ) NO PRIMARY INDEX;
Insert Data:
INSERT INTO abc(period (TIMESTAMP '1999-12-31 00:00:00.000000', TIMESTAMP '1999-12-31 23:59:00.000000'));
After select
ef_dtm
------------------------------------------------------------
('1999-12-31 00:00:00.000000', '1999-12-31 23:59:00.000000')
Update Data:
nonsequenced validtime
UPDATE ABC
SET ef_dtm = PERIOD(begin(ef_dtm) + INTERVAL -'1' DAY, end(ef_dtm))
WHERE begin(ef_dtm) = TIMESTAMP '1999-12-31 00:00:00.000000';
After SELECT
ef_dtm
------------------------------------------------------------
('1999-12-30 00:00:00.000000', '1999-12-31 23:59:00.000000')
How to count days between date range with a specific day?
Example:
START_DT = January 1, 2014;
END_DT = January 31, 2014;
Day = :SampleDay
Sample Result:
Monday = 4,
Tuesday = 4,
Wednesday = 5
Please help. :|
Are you looking for something like this,
WITH t(date1, date2) AS
(
SELECT to_date('01/01/2014', 'dd/mm/yyyy'),
to_date('31/01/2014','dd/mm/yyyy')+1 -- Adding 1 to calculate the last day too.
FROM DUAL
)
SELECT count(days) day_count, day
DAY
FROM(
SELECT date1 + LEVEL -1 days,
to_char(date1 + LEVEL -1, 'FmDay') DAY, --Use `FmDay`, this will remove the Embedded spaces.
to_char(date1 + LEVEL -1, 'D') DAY#
FROM t
CONNECT BY LEVEL <= date2 - date1
)
WHERE day = 'Monday' --Filter with day, if you want to get the count for a specific day.
GROUP BY DAY, day#
ORDER BY day#;
You wont have a direct solution to this. In oracle you have this form to know what day of the week is a specific date:
to_char(to_date('01012014', 'ddmmyyyy'), 'Day')
I would recommend to you to make a store procedure with a simple algorithm which receive that three parameters and then display the information you need. Put it in a query and it is done.
The Problem: Given a day of the week (1, 2, 3, 4, 5, 6, 7), a starting date and an ending date, compute the number of times the given day of the week appears between the starting and ending dates not inclusive of a date for which there were no sales.
Context:
Table "Ticket" has the following structure and sample content:
i_ticket_id c_items_total dt_create_time dt_close_time
----------------------------------------------------------------------------
1 8.50 '10/1/2012 10:23:00' '10/1/2012 11:05:05'
2 10.50 '10/1/2012 11:00:00' '10/1/2012 11:45:05'
3 8.50 '10/2/2012 08:00:00' '10/2/2012 09:25:05'
4 8.50 '10/4/2012 08:00:00' '10/4/2012 09:25:05'
5 7.50 '10/5/2012 13:22:23' '10/5/2012 14:33:27'
.
.
233 6.75 '10/31/2012 23:20:00' '10/31/2012 23:55:39'
Details
There may or may not be any tickets for one or more days during a month. (i.e. the place was closed that/those day/s)
Days in which the business is closed are not regular. There is no predictable pattern.
Based on Get number of weekdays (Sundays, Mondays, Tuesdays) between two dates SQL,
I have derived a query which returns the number of times a given day of the week occurs between the start date and the end date:
DECLARE #dtStart DATETIME = '10/1/2013 04:00:00'
DECLARE #dtEnd DATETIME = '11/1/2013 03:59:00'
DECLARE #day_number INTEGER = 1
DECLARE #numdays INTEGER
SET #numdays = (SELECT 1 + DATEDIFF(wk, #dtStart, #dtEnd)-
CASE WHEN DATEPART(weekday, #dtStart) #day_number THEN 1 ELSE 0 END -
CASE WHEN DATEPART(weekday, #dtEnd) <= #day_number THEN 1 ELSE 0 END)
Now I just need to filter this so that any zero-dollar days are not included in the count. Any help you can provide to add this filter based on the contents of the tickets table is greatly appreciated!
If I understand correctly, you can use a calendar table to count the number of days where the day of week is n and between the start and end and is a date that has ticket sales, which I guess is when the date exists in tickets and has the sum(c_items_total) > 0
WITH cal AS
(
SELECT cast('2012-01-01' AS DATE) dt, datepart(weekday, '2012-01-01') dow
UNION ALL
SELECT dateadd(day, 1, dt), datepart(weekday, dateadd(day, 1, dt))
FROM cal
WHERE dt < getdate()
)
SELECT COUNT(1)
FROM cal
WHERE dow = 5
AND dt BETWEEN '2012-04-01' AND '2012-12-31'
AND EXISTS (
SELECT 1
FROM tickets
WHERE cast(dt_create_time AS DATE) = dt
GROUP BY cast(dt_create_time AS DATE)
HAVING sum(c_items_total) > 0
)
OPTION (MAXRECURSION 0)
SQLFiddle
I have an Oracle table that contains data similar to the following:
ID | STATUS | TIME
-------------------------------
1 | IN | 2013/26/03 00:00
1 | OUT | 2013/26/03 07:00
1 | IN | 2013/27/03 03:00
2 | IN | 2013/26/03 01:00
2 | OUT | 2013/26/03 06:00
3 | IN | 2013/26/03 01:30
.
.
The STATUS represents check-in and check-out, where the ID represents individuals.
I've come up with a query using sub-queries but it seems inelegant and inefficient. Is it possible to write a single query (meaning no sub-queries) to calculate an elapsed time (IN -> OUT) for each ID?
UPDATE: Also, would it be possible to display the elapsed time the individual is OUT? For example in the data listed above Individual #1 is IN for 7 hours, but OUT for 20 hours (2013/27/03 03:00 - 2013/26/03 07:00). Since this would be calculated across records I'm not sure how this can be written.
try this
select timein.id, 24 * (timeout.time - timein.time) ElapsedTime
from t timein
left outer join t timeout on timein.id = timeout.id
where timein.status = 'IN' and timeout.status = 'OUT'
if your time field is char datatype then you need to do this
select timein.id, 24 * (TO_DATE(timeout.time, 'YYYY-DD-MM hh24:mi')
- TO_DATE(timein.time, 'YYYY-DD-MM hh24:mi')) ElapsedTime
from t timein
left outer join t timeout on timein.id = timeout.id
where timein.status = 'IN' and timeout.status = 'OUT'
try this for days with time
select timein.id, NUMTODSINTERVAL((timeout.time - timein.time),'day') ElapsedTime
from t timein
left outer join t timeout on timein.id = timeout.id
where timein.status = 'IN' and timeout.status = 'OUT'
For In and Out time you can use this and modify according to your data
with cte as
(
select t.id, status,
24 * (t.time - LAG(t.time)
OVER (partition by id ORDER BY t.time)) AS diff
from t
)
select t1.id, t1.diff timeIn, t2.diff timeOut
from cte t1
LEFT OUTER JOIN
cte t2 on t1.id = t2.id and t2.status = 'IN' and t2.diff is not null
where t1.status = 'OUT'