I'm building hourly report from SQL Table CONFIRMATION via SQL Query. Query absolutely runs fine and gives proper results as follow:
SELECT DATEPART(hh, CONFIRMATION.DATECOMPLETE) AS hour, sum( CONFIRMATION.QUANTITY) Units
FROM CONFIRMATION
WHERE CONFIRMATION.DATECOMPLETE >= '11/18/2015'
GROUP BY DATEPART(hh, CONFIRMATION.DATECOMPLETE)
I want to change Hour to have follwoing instead of hour number:
Hour Units
10:00 - 11:00 4
11:00-12:00 8
How can I achieve that?
Thanks
You can convert the datetime hour component into a string to format the 10:00-11:00. You can then calculate the end time by adding 1 to the hour component and modulo 24 to wrap around at midnight.
CONVERT(varchar(2),DATEPART(hh,CONFIRMATION.DATECOMPLETE)) + ':00-' + CONVERT(varchar(2), (DATEPART(hh,CONFIRMATION.DATECOMPLETE)+1) % 24) + ':00'
When putting parts of dates together using concatenation, datename() is much better than datepart():
SELECT (DATENAME(hour, c.DATECOMPLETE) + ':00-' +
DATENAME(hour, DATEADD(hour, 1, c.DATECOMPLETE)) + ':00'
) as period,
SUM(c.QUANTITY) as Units
FROM CONFIRMATION c
WHERE c.DATECOMPLETE >= '2015-11-18'
GROUP BY (DATENAME(hour, c.DATECOMPLETE) + ':00-' +
DATENAME(hour, DATEADD(hour, 1, c.DATECOMPLETE)) + ':00'
);
In addition:
Use ISO standard date formats. Either YYYY-MM-DD or YYYYMMDD.
Table aliases make the query easier to write and to read.
Related
I am using SQL Server 2008. I have several rows of start_time and end_time. I want to calculate the average difference between these two times in a MM:SS format.
start_time | end_time
10:15:30 | 10:15:45
10:45:00 | 10:47:30
Row 1 would be a difference of 00:15, and row 2 would be a difference of 02:30. The average of the entire dataset would be 01:23 (1 minute and 23 seconds).
The code I'm using looks like the following, but only returns an integer.
AVG(DATEDIFF(MI,start_time,end_time))
Thanks in advance for your help.
You're close, but you should use DateDiff() to get the average number of seconds between the two fields, rather than the average number of minutes.
With SQL Server 2008 R2, you don't have access to TIMEFROMPARTS() which would simplify the display greatly, so you'll have to convert this into a VARCHAR to get the format you want.
;With AverageSeconds As
(
Select Avg(DateDiff(Second, Start_Time, End_Time))) AvgSec
From YourTable
)
Select Right('00' + Convert(Varchar, (AvgSec / 60)), 2)
+ ':'
+ Right('00' + Convert(Varchar, (AvgSec % 60)), 2)
From AverageSeconds
You can convert the dates in unixtimestamp and then convert the seconds in a string.
Alternatively
right(convert(varchar(20), Dateadd(second, Avg(Datediff(second, Start_Time, End_Time)), 0), 120), 5)
When using Datepart to group by week, is it possible to easily have it display the dates the weeks span. Below is an example of my sql:
SELECT
'Week ' + cast(datepart(wk, Table.ApplicationDate) AS VARCHAR(2)) Week
,year(Table.ApplicationDate) Year
,COUNT(Table.Value) AS [Applications]
FROM Table
GROUP BY datepart(wk, Table.ApplicationDate), year(GrantDetail.ApplicationDate)
Ideally I'd like to have Week 2 - 25/12/2015 - 31/12/2015
This will return the date ranges you are looking for. Note that using Min and Max only works if there are reliably entries for every possible day.
select 'Week ' + cast(datepart(wk, Table.ApplicationDate) as varchar (2))
+ ' - '
+ convert(varchar(8), dateadd(wk, datepart(wk, Table.ApplicationDate) - 1, '1-1-' + cast(datepart(YEAR, Table.ApplicationDate) as varchar)), 3)
+ ' - '
+ convert(varchar(8), dateadd(wk, datepart(wk, Table.ApplicationDate), '1-1-' + cast(datepart(YEAR, Table.ApplicationDate) as varchar)) - 1, 3)
You take January 1 of the year in question, then add the number of weeks (minus 1) you've calculated to that date to get the beginning of the week. Then add one more week, minus one day, to get the end of the week.
Edit: noticed you are using DD/MM rather than MM/DD, so edited my code to convert to the correct format.
If you can assume that all your dates are covered within the data then you can use min and max, otherwise you'll need to calculate them:
dateadd(dd, -datepart(dw, min(ApplicationDate)) + 1) as StartOfWeek,
dateadd(dd, -datepart(dw, min(ApplicationDate)) + 7) as EndOfWeek
I'm assuming the your datefirst settings corresponds to the logical week you want to use as you're already relying on that. Also double-check the documentation for datepart(wk, ...) to confirm it does what you're expecting especially for dates around the beginning and end of the year. (See the accepted answer at Difficulties comprehending ISO_week and week in Microsoft SQL, what's happening exactly?)
Some people prefer to avoid the old datepart codes so here are the equivalents:
dateadd(day, -datepart(weekday, min(ApplicationDate)) + 1) as StartOfWeek,
dateadd(day, -datepart(weekday, min(ApplicationDate)) + 7) as EndOfWeek
You may find it better to group on a count of the number of weeks since a fixed reference point. January 1, 2012 happened to be a Sunday so I'll use it. All of the same logic above will still work and it doesn't really matter if any of your data falls before that date since the value of the expression will just be a negative number:
group by datediff(wk, '20120101', ApplicationDate)
I want to select a range of data from today until the last 15th (so this month or last month). How would this be done in TSQL?
Following Get last Friday's Date unless today is Friday using T-SQL it seems like I would have to make use of DATEDIFF at the least.
I'm considering building a date string, like:
set #date='yyyy-mm-15'
But yyyy or mm would not be able to be simply the current year/month, in case it has to look back a month/year.
This should give you what you want
SELECT *
FROM YourTable
WHERE YourDate > CAST((
CASE
WHEN DAY(getdate()) < 15
THEN (CAST(YEAR(GETDATE()) AS CHAR(4)) + CAST(MONTH(dateadd(month, - 1, getdate())) AS CHAR(2)) + '15')
ELSE CAST(YEAR(GETDATE()) AS CHAR(4)) + CAST(MONTH(GETDATE()) AS CHAR(2)) + '15'
END
) AS DATETIME)
EDIT
changed WHEN DAY(getdate()) > 15 to WHEN DAY(getdate()) < 15, as the results were inverted :)
Format the current date in the format yyyy-mm-15, convert back to date, compare to the current date and if this is later that today, subtract 1 month.
That's what I'd do in ANSI SQL... But apparently, MS SQL Server doesn't know "interval". Well, you can make use of DateAdd instead:
DateAdd() - Returns a new datetime value based on adding an interval to the specified date.
Where first parameter specifies on which part of the date to return a new value: yy(yyyy) for Year, mm(m) for Month, dd(d) for Day etc.
For example: select dateadd(d,2,getdate()) - adds 2 days to current date and returns new date.
I have timediff field as varchar
I want to find sum of this field but it gives error as
"Syntax error converting the varchar value '02:00' to a column of data type int."
My timediff is like
02:00
03:00
04:00
i want to add and should display 9 in sql
please help me
thanks for helping me
You can't use SUM on a varchar column. Take a look at the documentation here.
You haven't given us much information about what you are storing or how you want it summed, but your best bet might be to parse out the number before your colon, convert it to an int and sum that.
Good luck!
If you are talking about MS SQL
You could do something like this
first convert your hour representation to minutes by this
select (CONVERT(int,SUBSTRING('02:00',1,2))*60) +
CONVERT(int,SUBSTRING('02:00',4,2))
Then use that minutes representation to perform addition like this
select
DATEADD(
minute,
(select (CONVERT(int,SUBSTRING('02:00',1,2))*60) +
CONVERT(int,SUBSTRING('02:00',4,2))),
getdate())
If your final goal is to get sum of all datadiff records in hh:mm then first store datediff in minutes instead of hh:mm which you asked here.
How to store DateDiff in minutes:
SELECT DATEDIFF(second,CAST(<timepart> AS DATETIME)
, CAST(<timepart> AS DATETIME))/60.0 AS MIN_DIFF;
For example
SELECT DATEDIFF(second,CAST('10:00 AM' AS DATETIME)
, CAST('11:15 AM' AS DATETIME))/60.0 AS MIN_DIFF;
How to do sum of all minutes in hh:mm
SELECT CAST((<total minutes> / 60) AS VARCHAR(8)) + ':'
+ CAST((<total minutes> % 60) AS VARCHAR(2))
For example
SELECT CAST((390 / 60) AS VARCHAR(8)) + ':'
+ CAST((390 % 60) AS VARCHAR(2))
See this fiddle for all your answers.
I want to calculate the Sum of the Field which has Time DataType.
My Table is Below:
TableA:
TotalTime
-------------
12:18:00
12:18:00
Here I want to sum the two time fields.
I tried the below Query
SELECT CAST(
DATEADD(MS, SUM(DATEDIFF(MS, '00:00:00.000',
CONVERT(TIME, TotalTime))), '00:00:00.000'
) AS TOTALTIME)
FROM [TableA]
But it gives the Output as
TOTALTIME
-----------------
00:36:00.0000000
But My Desired Output would be like below:
TOTALTIME
-----------------
24:36:00
How to get this Output?
You could sum the total number of seconds, or datediff(second,0,datecolumn). You can format that as a time string with some math. For example, the total number of minutes is totalseconds / 60 % 60. For example:
select cast(sum(datediff(second,0,dt))/3600 as varchar(12)) + ':' +
right('0' + cast(sum(datediff(second,0,dt))/60%60 as varchar(2)),2) +
':' + right('0' + cast(sum(datediff(second,0,dt))%60 as varchar(2)),2)
from TestTable
Working code at SQL Fiddle.
24:36 is the same as 00:36(Next day)
Your query is working fine the results are correct,
24:36 is the time 00:36 for next day.
You can display maximum 24 hrs. You are not using any day thats why every 24 hrs =0 hrs for next day.
Just change the column values and you can see that.
It would be a tad longwinded, but if you wanted to avoid the day rollover but you could split the second TIME into constituent datepart()'s and then add those on? (even display as a varchar if it's necessary to have an hour value greater than 24.
TRY THIS.
SELECT
CONVERT(VARCHAR(MAX),SUM(DATEPART(HH,CAST(YOUR_FIELD AS DATETIME)))+
(SUM(DATEPART(MINUTE,CAST(YOUR_FIELD AS DATETIME)))/60) +
(SUM(DATEPART(MINUTE,CAST(YOUR_FIELD AS DATETIME)))%60 +
(SUM(DATEPART(SECOND,CAST(YOUR_FIELD AS DATETIME)))/60))/60) + ':' +
RIGHT('00' + CONVERT(VARCHAR(MAX),
(SUM(DATEPART(MINUTE,CAST(YOUR_FIELD AS DATETIME)))%60+
(SUM(DATEPART(SECOND,CAST(YOUR_FIELD AS DATETIME)))/60))%60),2) + ':' +
RIGHT('00' + CONVERT(VARCHAR(MAX),SUM(DATEPART(SECOND,
CAST(YOUR_FIELD AS DATETIME)))%60),2) AS YOUR_FIELD
FROM YOUR_TABLE