Employee Total Experience SQL query - sql

I have table with employees work experience. I want to get summary experience in format like yy mm dd.
e_id work_from work_to
2 2003-10-13 2004-02-12
2 2004-02-16 2004-06-30
2 2004-07-01 2006-01-31
2 2006-02-01 2017-07-12
Result should be: 13Y 8M 27D
Query like:
sum(datediff(month,work_from,work_to))/12,
sum(datediff(month,work_from,work_to)%12
works fine, but what about days?

Please note, the following query is a general summation which does not include leap years and the months are averaged between 365/12 in days since the amount of days in each month vary. If you want an exact figure that includes the exact amount of days, the algorithm will be more involved, but hopefully this gets you in a reasonably close ballpark figure.
SELECT CONVERT(VARCHAR(10), sum(datediff(year,work_from,work_to))-1) + 'Y' AS Years,
CONVERT(VARCHAR(10), FLOOR((sum(datediff(day, work_from,work_to)) - ((sum(datediff(year,work_from,work_to)) - 1) * 365)) / 30.4166)) + 'M' AS Months,
CONVERT(VARCHAR(10), CEILING(sum(datediff(day, work_from,work_to)) - ((sum(datediff(year,work_from,work_to)) - 1) * 365) - (FLOOR((sum(datediff(day, work_from,work_to)) - ((sum(datediff(year,work_from,work_to)) - 1) * 365)) / 30.4166) * 30.4166))) + 'D' AS Days,
CONVERT(VARCHAR(10), sum(datediff(day,work_from,work_to))) AS Total_Days

Here is my solution. This is the closest I can get. The problem that I had is that I cant escape the M after month.
DECLARE #SumExp Datetime = (SELECT CONCAT(
DATENAME(day, (SELECT SUM(DATEDIFF(day, WorkFrom, WorkTo))
FROM EmployeeWorkExperience)),
DATENAME(month, (SELECT SUM(DATEDIFF(day, WorkFrom, WorkTo))
FROM EmployeeWorkExperience)),
DATENAME(year, (SELECT SUM(DATEDIFF(day, WorkFrom, WorkTo))
FROM EmployeeWorkExperience))))
SELECT REPLACE(FORMAT(#SumExp, 'yyY MM# ddD'), '#', 'M')

DECLARE #work TABLE(
WorkId INT IDENTITY(1,1) PRIMARY KEY ,
work_from DATETIME NOT NULL,
work_to DATETIME NOT NULL )
INSERT INTO #work
( work_from, work_to )
VALUES ( '10/13/2003',
'2/12/2004'
),
(
'2/16/2004',
'6/30/2004'
),
('7/1/2004',
'1/31/2006'
),
('2/1/2006',
'7/12/2017'
)
DECLARE #seconds int
SELECT #seconds = SUM(DATEDIFF(SECOND, work_from, work_to))
FROM #work
DECLARE #VARDT DATETIME = DATEADD(SECOND, #seconds, 0)
SELECT CAST(DATEPART(YEAR, #VARDT) - 1900 AS VARCHAR(10)) + ' year(s) ' + CAST(DATEPART(MONTH, #VARDT) - 1 AS VARCHAR(2)) + ' month(s) '
+ CAST(DATEPART(DD, #VARDT) - 1 AS VARCHAR(2)) + ' day(s) ' + CAST(DATEPART(HOUR, #VARDT) AS VARCHAR(2)) + ' hour(s) '
+ CAST(DATEPART(MINUTE, #VARDT) AS VARCHAR(2)) + ' minute(s) ' + CAST(DATEPART(SECOND, #VARDT) AS VARCHAR(2)) + ' second(s)'

Related

Multiply TIME in SQL Server

I have this query below, basically I'm trying to subtract 2 dates and get the hours.
However, I need the subtracted time to be multiplied by the number of cleaners
SELECT
CONVERT(TIME, ClientBooking.TimeEnd - ClientBooking.TimeStart) AS HoursWorked2,
ClientBooking.NumberOfCleaners AS NumberOfCleaners,
ClientBooking.TimeStart,
ClientBooking.TimeEnd,
ClientBooking.ClientID,
((((ClientInfo.FirstName + N' ') +
ClientInfo.LastName) + N' ') +
ClientInfo.Company) AS ClientName,
((((ClientInfo.Address + N' - ') +
ClientInfo.City) + N' - ') +
ClientInfo.ZipCode) AS Address,
((ClientInfo.PhoneNumber + N' ') +
ClientInfo.EmailAddress) AS Contact,
(ClientBooking.HourlyRate / 60) AS MinRate,
(DATEDIFF(MINUTE,ClientBooking.TimeStart,ClientBooking.TimeEnd) * ClientBooking.NumberOfCleaners) AS Quantity,
ClientBooking.HourlyRate,
DATEDIFF(HOUR, ClientBooking.TimeStart, ClientBooking.TimeEnd) AS HoursWorked
FROM
(dbo.ClientBooking ClientBooking
INNER JOIN
dbo.ClientInfo ClientInfo ON (ClientInfo.ClientID = ClientBooking.ClientID))
Basically, I need to multiply the result of this:
CONVERT(TIME,"ClientBooking"."TimeEnd" - "ClientBooking"."TimeStart" )
How About using this:
Select
convert(time,DATEADD(MINUTE, ( convert(float,(DATEDIFF(minute, ClientBooking.TimeStart, ClientBooking.TimeEnd) * ClientBooking.NumberOfCleaners))/60), ''))
FROM
(dbo.ClientBooking ClientBooking
INNER JOIN
dbo.ClientInfo ClientInfo ON (ClientInfo.ClientID = ClientBooking.ClientID))
Sorry if i have missed a parenthesis !!
You can use DATEDIFF() function..
Something like:
DATEDIFF(hour, ClientBooking.TimeStart, ClientBooking.TimeEnd) * ClientBooking.NumberOfCleaners
as your desired column!
If I understand you correctly this could help you:
declare #start datetime = '2018-11-02 07:00:00'
declare #end datetime = '2018-11-02 08:03:00'
declare #diff int
Select #diff = DATEDIFF(minute,#start,#end)
Select case
when #diff < 60 then concat('00:', right('0' + convert(varchar,#diff), 2))
when #diff >= 60 and #diff < 120 then '01:' + right('0' + convert(varchar,#diff - 60), 2)
when #diff >= 120 and #diff < 180 then '02:' + right('0' + convert(varchar,#diff - 120), 2)
when #diff >= 180 and #diff < 240 then '03:' + right('0' + convert(varchar,#diff - 180), 2)
end
Of course you would need to add the following hours as well.
I've splitted everything up, so it is easier to understand. But you should be able to write it in one line and without variables as well
Hope this helps.

Update a column with records from current row in SQL Server

I have an existing SQL Server table Employees with 3 columns month, year and day as date parts.
Now I have added a new column createdate where I want to insert date as a combination of all 3 columns from the current row.
UPDATE Employees
SET createdate = TRY_PARSE(CAST([year] AS VARCHAR(4)) + '/' + CAST([month] AS VARCHAR(2)) + '/' + CAST([day] AS VARCHAR(2)) AS DATETIME)
If you have invalid data in Month Or Year Or Day Colunm, then above query will update with NULL Value.
NOTE: Try_Parse will work from Sql Server Version 2012 onwards.
You can as the below:
UPDATE Employees
SET createdate = CAST(CAST(year AS VARCHAR(4)) + '.' + CAST(month AS VARCHAR(2)) + '.' + CAST(day AS VARCHAR(2)) AS DATETIME)
You can use DATEFROMPARTS very simple to form date
UPDATE Employees SET CreateDate =DATEFROMPARTS ( year, month, day )
Try this, it's update for all rows :
UPDATE Employees SET CreateDate = [day] +'/'+ [Month] +'/'+ [year]
1)...UPDATE Employees
set createdate =
CAST(
CAST(year AS VARCHAR(4)) +
RIGHT('0' + CAST(month AS VARCHAR(2)), 2) +
RIGHT('0' + CAST(day AS VARCHAR(2)), 2)
AS DATETIME)
2)...SELECT
DATEADD(year, [year]-1900, DATEADD(month, [month]-1, DATEADD(day, [day]-1, 0)))
FROM
dbo.Table
UPDATE emp SET CreateDate =( SELECT CONVERT(DATE,CAST([Year] AS VARCHAR(4))+'-'+
CAST([Month] AS VARCHAR(2))+'-'+
CAST([Day] AS VARCHAR(2))))
or
you can also use this code:
UPDATE empl SET CreateDate =( SELECT CONVERT(varchar(10),
CAST([Month] AS VARCHAR(2))+'-'+
CAST([Day] AS VARCHAR(2))+'-'+CAST([Year] AS VARCHAR(4)),101))

How to convert separated Year(int), Month(int) and Day(int) columns into DateTime

Our ERP system holds year, month and day in separate int columns. I want to combine those 3 int columns into one DateTime, How can I convert it in the SQL Server.
Year | Month | Day
--------------------
2016 | 1 | 23
You could use DATEFROMPARTS(SQL Server 2012+):
SELECT DATEFROMPARTS([Year], [Month], [Day]) AS DateTim
FROM table_name
SQL Server 2008 (assuming that year is 4-digit):
SELECT CAST(CAST([year] AS VARCHAR(4)) + '-' +
CAST([month] AS VARCHAR(2)) + '-' +
CAST([day] AS VARCHAR(2))
AS DATE) AS DateTim
FROM table_name;
LiveDemo
As Gordon Linoff proposed in comment to utilize YYYYMMDD as INT to convert to DATE:
SELECT CAST(CAST([year] * 10000 + [month]*100 + [day] AS VARCHAR(8))
AS DATE) AS DateTim
FROM table_name;
LiveDemo2
Addendum
To address ypercubeᵀᴹ concerns about dateformat we could utilize ISO-8601 which is not affected by DATEFORMAT or LANGUAGE settings:
yyyy-mm-ddThh:mm:ss[.mmm]
SELECT CAST(RIGHT('000'+ CAST([year] AS VARCHAR(4)),4) + '-' +
RIGHT('0' + CAST([month] AS VARCHAR(2)),2) + '-' +
RIGHT('0' + CAST([day] AS VARCHAR(2)),2) + 'T00:00:00' AS DATE)
FROM table_name
LiveDemo3
To handle years before 1000 should be padded with zeros.
We can use SQL's CONVERT function to get Datetime value :
SELECT CONVERT(DATETIME, CONVERT(VARCHAR(2), Day) + '/' + CONVERT(VARCHAR(2), Month) + '/' + CONVERT(VARCHAR(4), Year),103) FROM Table_Name

if minute is less than 60 then remove hour part from result

I have a function like this:
ALTER FUNCTION [dbo].[testfunctionstacknew] (#dec NUMERIC(18, 2)) RETURNS Varchar(50)
AS
BEGIN
DECLARE
#hour decimal(18,2),
#Mns decimal(18,2),
#second decimal(18,3)
DECLARE #Average Varchar(50)
select #hour=CONVERT(int,#dec/60/60)
SELECT #Mns = convert(int, (#dec / 60) - (#hour * 60 ));
select #second=#dec % 60;
SELECT #Average =
convert(varchar(9), convert(int, #hour)) + ':' +
-- right('00' + convert(decimal(10,0), convert(decimal(18,2), #hour)), 2) + ':' +
right('00' + convert(decimal(10,0), convert(decimal(18,2), #Mns)), 2) + ':' +
right('00' + CONVERT(decimal(10,0), convert(varchar(10), #second)), 6)
RETURN #Average
END
and i have a stored procedure like this:
select dbo.testfunctionstacknew(
convert(decimal(10,1),
avg(convert(numeric(18,2), datediff(ss, t.dtime, t.PAICdate ))))
) as Avgparkingtime from (select top 10 * from transaction_tbl where locid=6 and dtime >= getdate()-1 order by transactID desc ) t
while executing stored procedure if the average time is less than 60 minutes i am getting result like this:
Avgparkingtime :
0:25:33
if the average time is less than 60 minutes then i dont want to get zero in front of minutes,,(this time only need to show minutes and seconds)..only hour need to show if the minutes is greater than 60 minutes...how i can do this? what changes i have to make in my function ?? any help is very appreciable..
Try changing the part where you build the formatted string like this:
SELECT #Average =
case
when convert(int, #hour) <> 0 then convert(varchar(9), convert(int, #hour)) + ':'
else ''
end +
right('00' + convert(decimal(10,0), convert(decimal(18,2), #Mns)), 2) + ':' +
right('00' + CONVERT(decimal(10,0), convert(varchar(10), #second)), 6)

Using DatePart in line of a larger sql clause

This statement will correctly merge 2 columns ('DATE' and 'TIME'):
update AllBW1 set sUserTime =
CAST(
(
STR( YEAR( [DATE] ) ) + '/' +
STR( MONTH( [DATE] ) ) + '/' +
STR( DAY( [DATE] ) ) + ' ' +
(select DATENAME(hour, [TIME]))+ ':' +
(select DATENAME(minute, [TIME])) + ':' +
(select DATENAME(SECOND, [TIME]))
) as DATETIME)
where sUserTime is null
I'd like to refine the above so as to replace the default timezone with my own (GMT-6).
I've tried a few variations:
CAST((select DATEADD(hour, -6, DATENAME(hour, [TIME]))) as smalldatetime) + ':' +
and
(select CAST(DATEADD(hour, -6, DATENAME(hour, [TIME]))) as datetime) + ':' +
and have achieved no joy.
thx
The logfile as parsed into the SQL table by LogParser 2.2 has separate fields for Date and Time but, since both are formatted as datatime fields they end up looking like:
2012-01-04 00:00:00.000 for date (all time fields are zeroed)
2012-01-01 06:04:41.000 for time (all date field = first day of current year)
That's the reason the query is parsing each element the way it is. Thanks to Dems comment I simplified everything down. I've no doubt this can be optimized by for the volumes I'm dealing with this is adaquate:
update myTable set sUserTime =
(
DATENAME(YEAR, [DATE] ) + '/' +
DATENAME(MONTH, [DATE] ) + '/' +
DATENAME(DAY, [DATE] ) + ' ' +
DATENAME(hour, (dateadd(hh, -6, [time])))+ ':' +
DATENAME(minute, [TIME]) + ':' +
DATENAME(SECOND, [TIME])
)
where sUserTime is null