Snowflake: calculate seconds difference between date and start of that date - snowflake-cloud-data-platform

Let’s say I have a table that has one column as timestamp ntz. I want to perform a select that calculates the number of seconds difference between that moment in the table vs the start of that date. For pure timestamp type I can just use the timediff function:
select timediff(second,
‘2022-01-01 00:00:05’::timestamp_ntz,
‘2022-01-01 00:00:00’::timestamp_ntz
)
Which returns 5.
How can I do it with a value in a table, for example:
select timediff(second, my_date, my_date_startofdate)
Where my_date_startofdate will be converted to that day but at time 00:00:00.

Use date_trunc. This function takes a timestamp or date and truncates it to whatever element you want. So, if you take your timestamp column and trunc it day, it removes the time elements and gives you the beginning of the day.
select timediff(second, date_trunc('day',my_date), my_date)
https://docs.snowflake.com/en/sql-reference/functions/date_trunc.html

Related

Partition and group by query

I have table containing the columns:
1. ClockifyId,
2. StartTime EndTime of every Task
3. Date.
4. Duration
The image is attached below
My goal is to write query to calculate the total duration of every user(which is ClockifyId) of every date.
As One User can have multiple task in one day, I wanted to sum duration of all those task. In short,
I wanted to have total task duration of every user(which is clockifyid) of every date.
enter image description here
There are a couple of details missing here, but this should get you close enough.
The first thing you need to do is convert the StartTime and EndTime to datetime fields if they aren't already. Doing a DATEDIFF on them allows you to figure out per record what the difference in minutes is. You can change the unit of measure as needed.
Once you do that, you use the SUM() which is an aggregate function. This makes it necessary to use the GROUP BY. You then group by which ever fields, in this case the ClockifyId and the StartTime as a date. You have to do it as a date without the datetime or you will get multiple rows back for a single Clockify record in a day.
SELECT
ClockifyId
, SUM(DATEDIFF(mi, CAST(StartTime AS datetime), CAST(EndTime AS datetime))) AS DurationInMinutes
, CAST(StartTime AS date)
FROM TableName
GROUP BY
ClockifyId
, CAST(StartTime AS date)
It's worth noting that this assumes there is always a valid StartTime and EndTime. This will throw some errors if those fields have nulls.

KDB Select from partitioned table where date is less than a given date - 1 day

I would like to select from a partitioned table where the date is the highest date strictly below a given date d.
I can do the following:
d:2019.10.02;
{select from x where date = max date} select from t where date < d
where t is my partitioned table.
The issue with the above query is that it is very slow as it has to first load all the dates strictly older than d, and then taking the max date out of it.
To select all the dates that are earlier than your specified date you can use the select statement below:
select from t where date=max date where date<d
Where t is your partitioned table and d is your specified date.
If you just want to select from the max date in a date partitioned hdb
Lets assume that the max populated date partition less than 2019.08.20 is 2019.08.07
q)d:2019.08.20
q)select from t where date=max date where date<d
This is because the partition type is available as a variable once you load into a DB, (i.e,. date, month, int etc). This will be the .Q.pf variable.
select from table where date=(last .Q.pv where .Q.pv < d)
kdb+ stores a variable in memory which contains all the dates within your db.
select from telemetry where date=desc[date]1
Above where clause will sort this by largest ->smallest
Selecting index 1 will filter the max date out of your query (without first querying the entire dataset).

How to generate an unnested array in BigQuery using existing timestamp

I'd like to take this query (which works for me):
SELECT(DATE_ADD(DATE(CURRENT_TIMESTAMP()), INTERVAL 1* n MONTH)) as date
FROM UNNEST(GENERATE_ARRAY(0,12,1)) n
And replace the CURRENT_TIMESTAMP() with a start_date timestamp field from an existing table.
In other words, I'd like to create a list of "active months" for a contract that begins on start_date.
I'm getting stuck on how to incorporate another FROM clause!
This should work:
SELECT(DATE_ADD(DATE(start_date), INTERVAL 1* n MONTH)) as date
FROM ExistingTable, UNNEST(GENERATE_ARRAY(0,12,1)) n
If you have exactly one row in the existing table representing the start date, you can use a subselect:
SELECT(DATE_ADD(DATE((SELECT start_date FROM ExistingTable)), INTERVAL 1* n MONTH)) as date
FROM UNNEST(GENERATE_ARRAY(0,12,1)) n

How to use stored procedure to calculate DateTime difference in hours?

I have two tables, TicketReport and TimeTracker.
TicketReport Columns:
Ticket_Number
Report_DT (DateTime ticket was reported)
Response_Time (Hourly value. How long it took for this ticket to be responded to. This is where I need the place the hours. DateTime Reported minus DateTime started)
TimeTracker Column:
Ticket_Number
Time_Start( DateTime that work started on this ticket)
Right now, for every row in my TicketReport table, the Response_Time column contains either Null or just a test value of 1(hour).
*I need to calculate how many hours it took for a ticket to be responded to (ReportDT - Time_Start), and then insert that hourly value into the Report_DT column for each row in the TicketReport table.
I did some research and found DATEDIFF, but I think this only returns days, and even if it did return hours, im not sure how to use it.
How could I accomplish this in a stored procedure?
To update the response_time column with the number of hours you can use a simple update query (which you could wrap in a stored proc if you need.
The query could look like this:
-- uncomment the next line to create a sp...
-- create proc update_response_time as
update tr
set response_time = datediff(hour, report_dt, time_start)
from TicketReport tr
join TimeTracker tt on tr.Ticket_Number = tt.Ticket_Number
If you want to run it without updating (to see what the values would be) you can run it as a select query:
select *, datediff(hour, report_dt, time_start) as diff_in_hours
from TicketReport tr
join TimeTracker tt on tr.Ticket_Number = tt.Ticket_Number
Be aware that these queries assume that there are just one matching row in the TimeTracker table for each ticket. If there can be multiple rows you would need another solution. Also know that the hour value doesn't take minutes into account at all so if report_dt is at 12:00 and time_start is at 12:30 it would be reported as 0 hours, so maybe a finer granularity than hours would be more suitable.
You can use DATEDIFF function
Syntax
DATEDIFF ( datepart , startdate , enddate )
pass datepart hh to get hours

SQL server 2005 - query aribitrary time interval in date range

I have a DateTime column. I want to extract all records, lets say, from 8:30 to 16:15 within a certain date range. My problem is that I need to compare hour and minute as a single time value. I can test the DATEPART for Greater or Less than some hours value, but if I then do that for minutes my query will fail if the later-in-the-day time has a smaller minutes value.
I have looked at INTERVAL, BETWEEN, DATEPART, DATEDIFF etc, but don't see quite how to to this without a "TimeOfDay" value that I can use across records of different dates.
I have tried subtracting the year, month and day parts of the date so that I can compare just the time of day, but when attmpting to subract, say, the year part of a date I get an overlfow error:
This part works:
select - cast( DATEPART(YEAR, CallTime) as integer) from history
This fails:
select DATEADD(YEAR, - cast( DATEPART(YEAR, CallTime) as integer), CallTime)
from history where calltime is not null
I have also tried casting the hours and minutes parts to chars, concatenating them and comparing to my target range, but this also fails.
I believe newer versions of SQL server may have a function to deal with this situation, but that's not available to me.
I hope and imagine there is a simple, obvious solution to this, but it's eluding me.
Try creating a "MinuteOfDay" function that calculates how many minutes have passed in the day based on a datetime.
CREATE FUNCTION dbo.[MinuteOfDay]
(
#dt datetime
)
RETURNS int
AS
BEGIN
RETURN (datepart(hh,#dt)*60) + datepart(mi,#dt)
END
then use the result of that function to filter.
select *
from MyTable t
where dbo.MinuteOfDay(t.SomeDateTimeColumn) between dbo.MinuteOfDay('1900-1-1 08:30:00') and dbo.MinuteOfDay('1900-1-1 16:15:00')
give this a shot:
DECLARE #StartDateTime datetime
,#EndDateTime datetime
--date range is ALL of January 1st up to & including 31st
SELECT #StartDateTime='2011/01/01'
,#EndDateTime='2011/01/31'
SELECT
*
FROM TableName t
WHERE
t.ColumnDate>=#StartDateTime AND t.ColumnDate<#EndDateTime+1 --date range
AND LEFT(RIGHT(CONVERT(char(19),t.ColumnDate(),120),8),5)>='08:30' --time range start
AND LEFT(RIGHT(CONVERT(char(19),t.ColumnDate(),120),8),5)<='16:15' --time range end
if you have an index on t.ColumnDate, this should be able to take advantage of it.
the "date range" part of the WHERE throws away rows that are not within the intended date range. The "time range start" part of the WHERE throws away rows that are to early in time and the "time range end" throws away rows that are to late.
DATETIME values can be cast as FLOAT. Actually, a DATETIME is stored as a FLOAT.
The whole part of the FLOAT is the days since '12/31/1899' (or something close). The fractional part is the number of hours divided by 24. So 0.5 = 12 Noon.
08:30 is 0.3541666667
16:15 is 0.6770833333
SELECT CAST(CAST('2011-03-25 08:30:00' AS DATETIME) AS FLOAT) = 40625.3541666667
SELECT CAST(CAST('2011-03-25 16:15:00' AS DATETIME) AS FLOAT) = 40625.6770833333
So you could write
SELECT * FROM users WHERE hire_date < 40625.3541666667
Using a DATETIME as FLOAT you can use whichever mathematical functions work best for your query.

Resources