I need to group data in intervals of 15 (or X) minutes in sql.
For example, i have the next scenario.
The result that i expect to obtain is
I tried using Lag function but i dont get what i want, because it add interval to each row and continues grouping.
Thanks in advance and apologies for my bad english.
If you want the intervals to be calendar based -- i.e. four per hour starting at 0, 15, 30, and 45 minutes, then you can use:
select id, min(begin_date), max(begin_date)
from t
group by id, convert(date, begin_date),
datepart(hour, begin_date), datepart(minute, begin_date) / 15;
Note that begin date and end date have the same value, so I just used begin_date in this answer.
Related
I need to calculate the time differences on a given day. I tried something like that but not works.
CONVERT(TIME, DATEADD(MINUTE, DATEDIFF(MI, MIN(CreatedOn),
MAX(CreatedOn)), 0), 108) AS WorkingTime
Thanks guys
You can try this way, since you don't show the error you get I don't know what detail you can have, but to get the time difference you can get it like this as I leave you here below
DECLARE #MaxDate DATETIME=DATEADD(HOUR,20,GETDATE()) --here you could get the maximum of your table separately
DECLARE #MinDate DATETIME=GETDATE() --here you could get the minimum of your table separately
SELECT DATEDIFF(MINUTE,#MinDate,#MaxDate) AS WorkingTime
https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=09128de0d996e85a21992197b524a208
Your question is not entirely clear, but I think this is what you're trying to do.
SELECT CAST(WorkingTime AS DATE),
MIN(WorkingTime) AS min,
MAX(WorkingTime) AS max,
DATEADD(HOUR, DATEDIFF(HOUR, 0, MIN(WorkingTime)), 0) AS truncatedmin,
DATEDIFF(MINUTE,DATEADD(HOUR, DATEDIFF(HOUR, 0, MIN(WorkingTime)), 0),MAX(WorkingTime)) AS [difference]
FROM YourTable
GROUP BY CAST(WorkingTime AS DATE)
The column called "difference" should show the number of minutes difference between the truncatedmin and max columns.
From this column I need to calculate the working time for each day, for this I need to select the first time on a given day and then round it to the full hour (06:08:20 to 06:00:00) and then calculate the differences between the last time in day, which will give me the working time in minutes.
My column
Its an interesting question I came across with.
I have an table
create table phonebook(
customer_id (varchar 30)
call_start_day (date)
call_end_day (date)
call_start_time (varchar 30)
call_end_time (varchar 30)
called_number (integer)
customer_call_location_city (varchar 30)
customer_call_location_state (varchar 30)
customer_call_location_zip (integer)
called_number_city (varchar 30)
called_number_state (varchar 30)
)
I need to to find top n customer based on average monthly call_duration in last 12 months. (consider only complete months only e.g., if current date is 2021-03-07, last 12 months: 2020-03-01 – 2021-02-28. Monthly call duration = sum (call duration) where call duration = time difference of call_end_day+ call_end_time and call_start_day+call_start_time)
Solution- I thought to find out the time and then their average. Any Suggestions?
In SQL Server, start by working out expressions that give
the first date you want to consider.
the day after the last date you want to consider.
EOMONTH() is good for this.
SELECT DATEADD(DAY, 1, EOMONTH(GETDATE(),-1)) day_after_last,
DATEADD(DAY, 1, EOMONTH(GETDATE(), -13)) first
Next, figure out how to get the call duration. You haven't told us how you represent your call_start_time and call_end_time, so we can't help you with that detail. So I'll represent the duration calculation as a stored function. It's up to you to figure out how to get the duration. Probably duration in seconds is the best way to go for call detail records.
Pro tip Never, never use varchars or chars to represent DATE, TIME, or DATETIME data. They always lead to confusion and grief.
Here's the way to go.
SELECT TOP (5) customer_id,
AVG(dbo.duration(call_start_day, call_start_time,
call_end_day, call_end_time)) average
FROM phonebook
WHERE call_start_day >= DATEADD(DAY, 1, EOMONTH(GETDATE(), -13))
AND call_start_day < DATEADD(DAY, 1, EOMONTH(GETDATE(),-1))
GROUP BY customer_id
ORDER BY 2 DESC;
The WHERE clause pulls in only the records with dates you care about.
The ORDER BY 2 DESC clause means order by the result set's second column, highest to lowest. The TOP (5) clause means display the first five rows of the ordered result set.
Edit
If your time columns look like 08:47:13 then you can compute the durations with DATEDIFF(). It looks like this
DATEDIFF(
second,
CAST(call_start_day AS DATETIME) + CAST(call_start_time AS DATETIME),
CAST(call_end_day AS DATETIME) + CAST(call_end_time AS DATETIME))
So your query looks like this:
SELECT TOP (5) customer_id,
AVG(
DATEDIFF(
second,
CAST(call_start_day AS DATETIME) +
CAST(call_start_time AS DATETIME),
CAST(call_end_day AS DATETIME) +
CAST(call_end_time AS DATETIME))) average
FROM phonebook
WHERE call_start_day >= DATEADD(DAY, 1, EOMONTH(GETDATE(), -13))
AND call_start_day < DATEADD(DAY, 1, EOMONTH(GETDATE(),-1))
GROUP BY customer_id
ORDER BY 2 DESC;
I'm trying to write a query to give me a countdown column that counts to a different number based on another variable in the row.
So if the data in column 'a_type' is '3', I need it to count down starting at 30 days, for all other scenarios I need it to count down starting at 60 days.
I've got the countdown part working, just not the dynamic change. Any help would be awesome!
SELECT disturbance_date,dist_type,daysleft = DATEDIFF(DAY, getdate(), DATEADD(DAY, 60, disturbance_date))
FROM cwr_prime
Below is the result I'd like to achieve:
If I'm reading the question correctly, I think you may be looking for a CASE expression inside your DATEADD function.
SELECT
ID,
a_date,
a_type,
daysleft = DATEDIFF
(
DAY,
getdate(),
DATEADD(DAY, CASE WHEN a_type = 3 THEN 30 ELSE 60 END, a_date)
)
FROM a_table;
I am new to tableau and i need to find all row set filter on basis of given time frame and then grouping the result of same minute.I can crack this problem in Sql as following
select count(x)
from table t
where datediff(30, min, date)
group by datepart(min, date)
How to fix it in tableau ?
I'm not really sure of what you want but this will give you the number of record per minute, for the records whose date is in the last 30 minutes:
select datepart(MI, date) , COUNT(*) as NumberOfRecordsInMinute
from table t
where date >= dateADD(MI, -30, getdate())
group by datepart(MI, date)
order by datepart(MI, date)
It isn't obvious what your SQL is trying to do here as the standard SQL datediff function works like this datediff(datepart,startdate,enddate) and returns the difference between two dates in the units specified.
If that is what you want, then the Tableau function datediff does much the same job and datediff('minute',start date,enddate) will return the number of minutes between two datetimes and it will be grouped already because the result is discrete.
You can then count the number of records matching each minute difference.
please help me with my problem. So, I have a table named 'RATES' which contains these columns:
id (int)
rate (money)
start_time (datetime)
end_time(datetime)
example data:
1 150 8:00am 6:00pm
2 200 6:00pm 4:00am
3 250 8:00am 4:00am (the next day)
What I have to do is to select all the id(s) to where a given time would fall.
e.g given time: 9:00 pm, the output should be 2,3
The problem is I got this time range between 8am to 4am the next day and I don't know what to do. Help, please! thanks in advance :D
Assuming that #Andriy M is correct:
Data never spans more than 24 hours
if end_time<=start_time then end_time belongs to the next day
then what you're looking for is this:
Declare #GivenTime DateTime
Set #GivenTime = '9:00 PM'
Select ID
From Rates
Where (Start_Time<End_Time And Start_Time<=#GivenTime And End_Time>=#GivenTime)
Or (Start_Time=End_Time And Start_Time=#GivenTime)
Or (Start_Time>End_Time And (Start_Time>=#GivenTime Or End_Time<=#GivenTime))
I don't really ever use MS SQL, but maybe this will help.
I was going to suggest something like this, but by the way you have your data set up, this would fail.
SELECT id FROM RATES
WHERE datepart(hh, start_time) <= 9 AND datepart(hh, end_time) >= 9;
You'll have you search using the actual date if you expect to get the correct data back.
SELECT id FROM RATES
WHERE start_time <= '2011-1-1 9:00' AND end_time >= '2011-1-1 9:00';
This may not be exactly correct, but it may help you look in the right direction.
I guess #gbn is not going to help you. I will try and fill in.
Given -- a table called timedata that has ranges only going over at most one day
WITH normalized AS
(
SELECT *
FROM timedata
WHERE datepart(day,start_time) = datepart(day,endtime)
UNION ALL
SELECT id, rate, start_time, dateadd(second,dateadd(day,datediff(day,0,end_time),0),-1) as end_time
FROM timedata
WHERE not (datepart(day,start_time) = datepart(day,endtime))
UNION ALL
SELECT id, rate,dateadd(day,datediff(day,0,end_time),0) as start_time, end_time
FROM timedata
WHERE not (datepart(day,start_time) = datepart(day,endtime))
)
SELECT *
FROM normalized
WHERE datepart(hour,start_time) < #inhour
AND datepart(hour,end_time) > #inhour
This makes use of a CTE and a trick to truncate datetime values. To understand this trick read this question and answer: Floor a date in SQL server
Here is an outline of what this query does:
Create a normalized table with each time span only going over one day by
Selecting all rows that occur on the same day.
Then for each entry that spans two days joining in
Selecting the starttime and one second before the next day as the end time for all that span.
and
Selecting 12am of the end_time date as the starttime and the end_time.
Finally you perform the select using the hour indicator on this normalized table.
If your ranges go over more than one day you would need to use a recursive CTE to get the same normalized table.