sum of time datatype in sql - sql

i have a table named tblAttendanceDailySummary and there is a field is in time datatype named timeAttendanceHour(like 09:44:25). I want to sum of this field due to end of the month.I mean one employee's one month working time need to calculate.How can i sum time datatype.

The time data type has a range of 00:00:00.0000000 through 23:59:59.9999999 so you can't cast to time. You have to calculate the hour, minute and second instead.
Something like this could work for you
select H.Val, M.Val, S.Val
from (
--Your query goes here
select dateadd(second, sum(datediff(second, 0, timeAttendanceHour)), 0) as sumtime
from YourTable
) as T
cross apply (select datedifF(hour, 0, T.sumTime)) as H(Val)
cross apply (select datediff(minute, 0, dateadd(hour, -H.Val, T.sumTime))) as M(Val)
cross apply (select datediff(second, 0, dateadd(hour, -H.Val, dateadd(minute, -M.Val, T.sumTime)))) as S(Val)
If you want the result as HH:MM:SS you can use this:
select cast(H.Val as varchar(10))+':'+right(M.Val+100, 2)+':'+right(S.Val+100, 2)

How about converting the components to a standard integer and summing them:
select sum(second(timeAttendanceHour))/60 +
sum(minute(timeAttendanceHour)) +
sum(hour(timeAttendance))*60 as MonthlyMinutes, intMonthID
from tblAttendanceDailySummary
where intYear = 2012
group by intEmployeeID, intMonthID

Related

Trying to convert a 7 digit julian date into MMDDYY format

I'm trying to convert a 7 digit julian/mainframe date into a calendar date of format mmddyy in SQL Server.
An example of this being julian date 2005020, where the first 4 digits are the year, 2005, and the last three are the day number in a calendar, so 020 = january 20. So I'd need to get this date as 012005(MMDDYY) in SQL Server.
I've been using the following query but keep getting an error after it loads a few records:
SELECT DATEADD(day,CAST(RIGHT([julianDateColumn],3) as int)-,LEFT([julianDateColumn],4))
The error I've been getting:
Conversion failed when converting date and/or time from character string.
Originally I was doing this in an Access DB using the "DATESERIAL" function but from what I've seen the closest thing to that in SQL Server was "DATEFROMPARTS", I tried using the following formula but it also didn't work:
DATEFROMPARTS([julianDateColumn]/1000,1,[julianDateColumn] % 1000)
Thanks in advance!
The simplest would seem to be to take the left as the year, and the add the days (-1) to make a date. Also, rather than using a format of MMDDYY I'm going to go straight a date datatype. If you want it in a specific format, that's for your presentation layer.
SELECT JulianDate,
CONVERT(date,DATEADD(DAY,RIGHT(JulianDate,3)-1,CONVERT(datetime,LEFT(JulianDate,4)))) AS ActualDate --4 int strings are iterpreted as the year, so I'm going to take advantage of that
FROM (VALUES('2005020'))V(JulianDate);
Based on the comments on the answer, it appears that the OP has some dates that don't conform to the format that stated (yyyyddd). Therefore what we could use here is a calendar table, here, and then LEFT JOIN to it and see what bad rows you get (and INNER JOIN to get the dates).
You can create the table with something like this:
CREATE TABLE dbo.CalendarTable (CalendarDate date NOT NULL PRIMARY KEY,
CalenderYear AS DATEPART(YEAR, CalendarDate) PERSISTED,
CalenderMonth AS DATEPART(MONTH, CalendarDate) PERSISTED,
CalenderDay AS DATEPART(DAY, CalendarDate) PERSISTED,
CalenderMonthName AS DATENAME(MONTH, CalendarDate),
JulianDate AS DATEPART(YEAR,CalendarDate) * 1000 + DATEDIFF(DAY,DATEFROMPARTS(DATEPART(YEAR, CalendarDate),1,1),CalendarDate) + 1 PERSISTED); --Some example columns
WITH N AS(
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1 AS I
FROM N N1, N N2, N N3, N N4, N N5, N N6),
Dates AS(
SELECT CONVERT(date,DATEADD(DAY, T.I, '19000101')) AS CalendarDate
FROM Tally T)
INSERT INTO dbo.CalendarTable(CalendarDate)
SELECT CalendarDate
FROM Dates
WHERE CalendarDate < '21000101';
GO
Then we can do something like this to get the bad rows:
SELECT YT.JulianDate
FROM dbo.YourTable YT
LEFT JOIN dbo.CalendarTable CT ON YT.JulianDate = CT.JulianDate
WHERE CT.JulianDate IS NULL;
I think I would use datefromparts() and dateadd():
select dateadd(day,
right(juliandate, 3) - 1),
datefromparts(left(juliandate, 4), 1, 1)
)
select Format(cast(concat(substring('2005020', 1, 4), '-', Month(cast(substring('2005020', 5, len('2005020')) as int)) ,'-', day(dateadd(day,-1,cast(substring('2005020', 5, len('2005020')) as int ) ) )) as date), 'MMddyy')

Query to check number of records created in a month.

My table creates a new record with timestamp daily when an integration is successful. I am trying to create a query that would check (preferably automated) the number of days in a month vs number of records in the table within a time frame.
For example, January has 31 days, so i would like to know how many days in january my process was not successful. If the number of records is less than 31, than i know the job failed 31 - x times.
I tried the following but was not getting very far:
SELECT COUNT (DISTINCT CompleteDate)
FROM table
WHERE CompleteDate BETWEEN '01/01/2015' AND '01/31/2015'
Every 7 days the system executes the job twice, so i get two records on the same day, but i am trying to determine the number of days that nothing happened (failures), so i assume some truncation of the date field is needed?!
One way to do this is to use a calendar/date table as the main source of dates in the range and left join with that and count the number of null values.
In absence of a proper date table you can generate a range of dates using a number sequence like the one found in the master..spt_values table:
select count(*) failed
from (
select dateadd(day, number, '2015-01-01') date
from master..spt_values where type='P' and number < 365
) a
left join your_table b on a.date = b.CompleteDate
where b.CompleteDate is null
and a.date BETWEEN '01/01/2015' AND '01/31/2015'
Sample SQL Fiddle (with count grouped by month)
Assuming you have an Integers table*. This query will pull all dates where no record is found in the target table:
declare #StartDate datetime = '01/01/2013',
#EndDate datetime = '12/31/2013'
;with d as (
select *, date = dateadd(d, i - 1 , #StartDate)
from dbo.Integers
where i <= datediff(d, #StartDate, #EndDate) + 1
)
select d.date
from d
where not exists (
select 1 from <target> t
where DATEADD(dd, DATEDIFF(dd, 0, t.<timestamp>), 0) = DATEADD(dd, DATEDIFF(dd, 0, d.date), 0)
)
Between is not safe here
SELECT 31 - count(distinct(convert(date, CompleteDate)))
FROM table
WHERE CompleteDate >= '01/01/2015' AND CompleteDate < '02/01/2015'
You can use the following query:
SELECT DATEDIFF(day, t.d, dateadd(month, 1, t.d)) - COUNT(DISTINCT CompleteDate)
FROM mytable
CROSS APPLY (SELECT CAST(YEAR(CompleteDate) AS VARCHAR(4)) +
RIGHT('0' + CAST(MONTH(CompleteDate) AS VARCHAR(2)), 2) +
'01') t(d)
GROUP BY t.d
SQL Fiddle Demo
Explanation:
The value CROSS APPLY-ied, i.e. t.d, is the ANSI string of the first day of the month of CompleteDate, e.g. '20150101' for 12/01/2015, or 18/01/2015.
DATEDIFF uses the above mentioned value, i.e. t.d, in order to calculate the number of days of the month that CompleteDate belongs to.
GROUP BY essentially groups by (Year, Month), hence COUNT(DISTINCT CompleteDate) returns the number of distinct records per month.
The values returned by the query are the differences of [2] - 1, i.e. the number of failures per month, for each (Year, Month) of your initial data.
If you want to query a specific Year, Month then just simply add a WHERE clause to the above:
WHERE YEAR(CompleteDate) = 2015 AND MONTH(CompleteDate) = 1

SQL statement to get a total for a given date range

I am trying to get the number of bookings and their total value by date for every day within a given date range.
My table looks like:
BookingId (int)
BookingFare (decimal)
BookingDateTime (datetime)
I can convert BookingDateTime to a date only by using:
SELECT CONVERT(varchar(8), BookingDateTime, 112) as BookingDateOnly
FROM [TaxiBookingOnline].[dbo].[Bookings]
What I'm after is something like this:
Date Bookings Value
2013-07-10 10 256.24
2013-07-11 12 321.44
2013-07-12 14 311.53
I get the feeling I should be aliasing the table, joining it to itself and then using 'GROUP BY' but I am failing to get this to work.
Any help would be much appreciated.
Thanks.
How about
select
cast(BookingDateTime as date) [Date],
count(*) [Bookings],
sum(BookingFare) [Value]
from t
group by cast(BookingDateTime as date)
SELECT CONVERT(VARCHAR(8), BookingsDateTime, 112) AS [Date],
COUNT(*) AS [Bookings],
SUM(BookingsFare AS [Value]
FROM MyTable
GROUP BY DATEADD(dd, 0, DATEDIFF(dd, 0, BookingDateTime))
Group by SELECT DATEADD(dd, 0, DATEDIFF(dd, 0, dateColumn)) which will effectively get the date portion of the datetime, then you can use count or sum as necessary on the grouped values.
EDIT: If you're using SQL Server >= 2008, you can cast to date (like #AlexK has done) otherwise you have to hack around it using DATEADD.
Following is the code. Replace Date1 and Date2 with the date range values:
SELECT
CONVERT(varchar(8), BookingDateTime, 112) as BookingDateOnly, BookingID Bookings,Sum(BookingFare)Value
FROM
[TaxiBookingOnline].[dbo].[Bookings]
WHERE BookingDateTime Between 'Date1' and 'Date2'
GROUP BY
BookingDateTime,BookingID
SELECT
CONVERT(DATE,BookingDateTime) BookingDate,
COUNT(BookingID) Bookings,
SUM(BookingFare) BookingFare
FROM TaxiBookingOnline.dbo.Bookings

SQL SELECT Only Closest To 15-Minute Timestamp

I would like to do a SQL SELECT for the closest value to each 15-minute time value. For example:
00:15,
00:30,
00:45,
01:00,
01:15 etc...
based on timestamps(time) that are not quite on the 00 second stamped using the following if have managed to round every value down to the closest 15 minutes but I only want the closest one e.g.
SELECT dateadd(minute, -1 * datediff(minute, 0,
cast(convert(varchar(20),[time],100) as smalldatetime)) % 15,
dateadd(minute, datediff(minute, 0, [time]), 0)) as [TIMESTAMP],
cast(convert(varchar(20),[time],100) as smalldatetime), [time],
tagname , value
FROM hdata
INNER JOIN rtdata
ON hdata.tag_id = rtdata.id
WHERE tagname = 'M1_WH_004'
order by [TIMESTAMP] desc
(note: i need the inner join to pull the tagname as they are not in the hdata table)
produces:
Therefore, for each 15 minutes, I only want the value closest to the 15-min boundary. For the data above, it would be the 09:45:15.383 and 09:30:17.463 for the data for 09:45 and 09:30 respectively.
Do I need a subquery or case statement?
Any help would be greatly appreciated!
Further to this, a had a table that looked like the data in the solution (data for every 15 minutes) already and the subquery performed a calculation based on the last two values like so:
SELECT DD1.[TIME_STAMP] AS [TIME_STAMP], DD1.[kWh1] AS [kWh1], DD1.[kWh2] AS [kWh2], (DD1.[kWh1] + DD1.[kWh2]) AS [Total] FROM (SELECT a.ID
,a.TIME_STAMP
,(a.[1_M1_Wh] - (SELECT TOP 1 b.[1_M1_Wh] FROM TagCapture b WHERE b.TIME_STAMP = DATEADD(MINUTE, -15, a.TIME_STAMP))) * 0.04 AS kWh1
,(a.[1_M2_Wh] - (SELECT TOP 1 b.[1_M2_Wh] FROM TagCapture b WHERE b.TIME_STAMP = DATEADD(MINUTE, -15, a.TIME_STAMP))) * 0.04 AS kWh2
FROM [TagCapture] a) DD1
How can I use the solution provided in this query? I'm a little confused with all the subqueries.
i.e. so based on the data defined by the t subquery take the count value for one 15 minute subtract from previous and multiply to get required value where would I insert the t subquery in each FROM clause? I can't seem to get it to work. The above is just where the t query would define the two different tagnames for 'M1' and 'M2'.
Thanks again in advance!!
It looks like you are using SQL Server. If so, then you can use row_number() to solve this.
select t.*
from (select t.*, row_number() over (partition by tagname, time15 order by time) as seqnum
from (SELECT dateadd(minute, -1 * datediff(minute, 0, cast(convert(varchar(20),[time],100) as smalldatetime)) % 15, dateadd(minute, datediff(minute, 0, [time]), 0)) as [TIMESTAMP], cast(convert(varchar(20),[time],100) as smalldatetime) as time15,
[time], tagname , value
FROM hdata INNER JOIN rtdata
ON hdata.tag_id = rtdata.id
WHERE tagname = 'M1_WH_004'
) t
) t
where seqnum = 1

sort distinct date column

I need distinct year and month from date column which would be sorted by same column.
I have date coulmn with values like (YYYY/MM/DD)
2007/11/7
2007/1/8
2007/11/4
2007/12/3
2008/10/4
2009/11/5
2008/5/16
after having query, it should be
2007/1/1
2007/11/1
2007/12/1
2008/5/1
2008/10/1
2009/11/1
This doesn't seems to be working
SELECT distinct (cast(year(datecol) as nvarchar(20) ) +
'/'+ cast(month(datecol) as nvarchar(20) ) + '/1') as dt1
FROM Table
ORDER BY dt1
Soemthing like this would work on MS SQL Server:
select
distinct
dateadd(day, -1 * DAY(datefield) + 1, datefield)
From
datetable
order by
dateadd(day, -1 * DAY(datefield) + 1, datefield)
The DATEADD function call basically subtracts (day-1) DAYS from the current date --> you always get the first of whatever month that date is in.
Sort by it and you're done! :-)
ADditionally, you could also add this functionality to your table as a "computed column" and then use that for easy acccess:
alter table yourTable
add FirstOfMonth As DATEADD(day, -1 * DAY(datefield) + 1, datefield) persisted
Then your query would be even simpler:
SELECT DISTINCT FirstOfMonth
FROM YourTable
ORDER BY FirstOfMonth
Marc
When dealing with dates in SqlServer avoid using cast like this - the resulting format will change depending on server config.
Instead use convert and choose a format (for instance 112) that adds leading zeros to the month.
Anil,
Do you also have time part in the dates ? What dataType are you using for the column ? Are you
using DateTime dataType or Char ?
This works for me
SELECT DISTINCT (DateField) AS Date FROM DateTable ORDER BY 1