Partition and group by query - sql-server

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.

Related

Formatting Y Axis with Day, Hour, Minute, and Second on a SSRS Report

Background of the problem:
I have this data set that provides me the solution I need for the chart. However, I have been struggling to find a solution for the report to correct produce the answer I need below.
The y axis is supposed to be something moving beyond the 24 hour time mark per vertical axis legend. The data set calculations are correct on the category groups, but the y axis is giving me a hard time to produce the formatting vertical label axis.
Query Used for this Report:
SELECT
-- Category Group for Chart
[Vendor_Name]
-- Date of call
[Call_Date],
-- Call Time in Seconds
[Call_Time],
-- DATE ADD function that does the conversion to days, hours, minutes, and seconds from Call_Time column beyond the 24 hour period.
DATEADD(SECOND, Call_Time, '00:00:00') [Call_Time_Test]
FROM Phone_Records
Methods Used:
Used T-SQL DATEADD() function to calculate the day, hour, minute, and hour, but it doesn't give the correct output that I am expecting.
Had changed the interval to Days but it didn't work for my case.
Used min and max values for the chart and did nothing for me.
Is there a better way to solve this problem without breaking any of code that I've made into the report so far?
You need to pass in a datetime to DATEADD, not just a time. With this in mind you can do something like this..
declare #t table (CallID int identity (1,1), CallDate DATETIME, CallTime int)
insert into #t (CallDate, CallTime) VALUES
('2022-08-16 23:50:00', 100),
('2022-08-16 23:50:00', 1000),
('2022-08-17 12:00:00', 1000),
('2022-08-17 13:00:00', 1000)
select
*
, CallDuration =cast(dateadd(s, CallTime , cast(cast(getdate() as date) as datetime)) as time)
from #t
It looks a bit messy and there probably is a better way to do it but it does work.
First to do GetDate() (any date will do) and cast it to Date so it ignores the time, we then cast this to DateTime to give use todays date at 00:00:00. Then we add the number of seconds to it and finally cast it back to a time so it chops the date off.
The above give the following results...

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

Creating a function to add a calculated column to a table in SQL Server based on a query

I have 2 database tables called Spend, and VendorSpend. The columns used in the Spend table are called VendorID, VendorName, RecordDate, and Charges. The VendorSpend table contains VendorID and VendorName but with distinct data (one record for each unique VendorID). I need a simple way to add a column to the VendorSpend table called Aug2015, this column will contain the SUM of each Vendor's charges within that month time period. It will be calculated based on this query:
Select Sum(Charges)
from Spend
where RecordDate >= '2015-08-01' and RecordDate <= '2015-08-31'
Keep in mind this will need to be called whenever new data is inserted into the Spend table and the VendorSpend table will need to update based on the new data. This will happen every month so actually a new column will need to be added and the data be calculated every month.
Any assistance is greatly appreciated.
Create a user-defined function that you pass a VendorID and Date to and which does your SELECT:
Select Sum(Charges)
from Spend
where VendorID=#VendorID
AND DATEDIFF(month, RecordDate, #Date) = 0
Now personally, I would stop right there and use the function to select your data at query time, rather than adding a new column to your table.
But treating your question as academic, you can create a computed column called [Aug2015] in VendorSpend that passes [VendorID] and '08/01/2015' to this function and it will contain the desired result.

Factoring public holidays in to a SQL code

Apologies if this is a simple one. I'm looking for some help with the following:
SELECT *
FROM (
SELECT TOP 7
RIGHT (CONVERT (VARCHAR, CompletedDate, 108), 8) AS Time,
WorkType
FROM Table
WHERE WorkType = 'WorkType1'
OR DATEPART (DW, CompletedDate) IN ('7','1')
AND WorkType = 'WorkType2'
ORDER BY CompletedDate DESC) Table
ORDER BY CompletedDate ASC
Multiple events run every day, and the above searches for the last one scheduled to run each day, and pulls the time from it for the past 7 days. This time marks the end of the day's events, and is the value I'm after.
Events run at a different order on weekends, so I search for a different WorkType. WorkType 1 is unique to weekdays. WorkType2 is run both at weekdays and weekends, however it is not the final event on a weekday, so I don't search for it then.
However, this kind of falls apart when public holidays such as bank holidays come into play, as they use the weekend timings. I still need to capture these times, but the above skips over them. If I were to remove or expand the DATEPART, I would end up with duplicate values for each day that don't mark the final job of the day.
What changes can I make to this to capture these lost holiday timings, without manually going through and checking every holiday? Is there a way that I can return a value for JobType2, if JobType1 does not appear on a day?
I suggest a materialized calendar table with one row per date along with the desired WorkType for that day. That will allow you to simply join on to the calendar table to determine the proper WorkType value without embedding the logic in the query itself.
With this table loaded with all dates for your reporting domain:
CREATE TABLE dbo.WorkTypeCalendar(
CalendarDate date NOT NULL
CONSTRAINT PK_Calendar PRIMARY KEY CLUSTERED
, WorkType varchar(10) NOT NULL
);
GO
The query can be refactored as below:
SELECT *
FROM ( SELECT TOP 7
RIGHT(CONVERT (varchar, CompletedDate, 108), 8) AS Time
, WorkType
FROM Table1 AS t
JOIN WorkTypeCalendar AS c ON t.WorkType = c.WorkType
AND t.CompletedDate >= c.CalendarDate
AND t.CompletedDate < DATEADD(DAY,
1,
c.CalendarDate)
ORDER BY CompletedDate DESC
) Table1
ORDER BY CompletedDate ASC
You also might consider making this a generalized utility calendar table. See http://www.dbdelta.com/calendar-table-and-datetime-functions/ for an complete example of such a table and script to load US holidays you can adjust for your needs and locale.

How to Get rows that are added 'x' minutes before in sqlserver?

I want to get all rows that have being added 'x' minutes before.
SELECT [PromoCodeID]
,[CustomerID]
,[DiscountAmount]
,[AddedBy]
,[AddedDate]
,[ModifiedBy]
,[ModifiedDate]
FROM [tbl_PromoCodesNewCustomer]
Where....
Eg: Records added 30min before from todays date time
NOTE: Record Added date is added in the field 'AddedDate' which has DATETIME datatype.
You can use this:
SELECT [PromoCodeID]
,[CustomerID]
,[DiscountAmount]
,[AddedBy]
,[AddedDate] AS added
,[ModifiedBy]
,[ModifiedDate]
FROM [tbl_PromoCodesNewCustomer]
WHERE DATEADD(minute,x,added) > GETDATE()
Where "x" in DATEADD is the number of minutes you want.
i suggest a light variation on FirstHorizon answer:
SELECT [PromoCodeID]
,[CustomerID]
,[DiscountAmount]
,[AddedBy]
,[AddedDate] AS added
,[ModifiedBy]
,[ModifiedDate]
FROM [tbl_PromoCodesNewCustomer]
WHERE AddedDate < DATEADD(minute * -1,x,getdate())
the change may look minor but depending on the number of involved rows, indexes and some other factor evaluated by the query optimizer this query may perform way better because there is no calc to make on the data.
here is an article that explain the reason (look at the second paragraph, 'Using Functions in Comparisons within the ON or WHERE Clause').
EDIT:
I'd advise you to populate the addedDate field with the UTC date and time, otherwise you could have problems with data managed among different servers \ time zones or on time change days.
So, if we consider this, the where clause will be:
WHERE DATEDIFF(mi,addedDate,GETUTCDATE)<30

Resources