Calculate amount after interest over time SQL Server 2012 - sql-server-2012

Initial Amount = $100
Interest Rate = 5%
Number of years = 3
Total Amount = $115.76
How would I calculate this in Sql Server?

Here's how I calculated total amount:
DECLARE #Current_LeaseEndDate DATE = '01/31/2021' --3 Years
DECLARE #PercentIncrease FLOAT = .05
DECLARE #Principal FLOAT = 100
SELECT
YEAR(DATEADD(day, 1, CAST(#Current_LeaseEndDate AS VARCHAR(10))) + 1),
CASE WHEN YEAR(DATEADD(day, 1, CAST(#Current_LeaseEndDate AS VARCHAR(10))) + 1) >= YEAR(GETDATE())
THEN #Principal * POWER((1 + #PercentIncrease), YEAR(DATEADD(day, 1, CAST(#Current_LeaseEndDate AS VARCHAR(10))) + 1) - YEAR(GETDATE()))
END AS MEH

Related

How to calculate the sum of time with SQL SERVER? [duplicate]

I have a column called "WrkHrs" and the data type is time(hh:mm:ss). I want to sum up the working hours for employees. But since it's time data type sql server doesn't let me use like sum(columnname).
How can I sum up the time data type fieled in sql query?
SELECT EmployeeID, minutes_worked = SUM(DATEDIFF(MINUTE, '0:00:00', WrkHrs))
FROM dbo.table
-- WHERE ...
GROUP BY EmployeeID;
You can format it pretty on the front end. Or in T-SQL:
;WITH w(e, mw) AS
(
SELECT EmployeeID, SUM(DATEDIFF(MINUTE, '0:00:00', WrkHrs))
FROM dbo.table
-- WHERE ...
GROUP BY EmployeeID
)
SELECT EmployeeID = e,
WrkHrs = RTRIM(mw/60) + ':' + RIGHT('0' + RTRIM(mw%60),2)
FROM w;
However, you're using the wrong data type. TIME is used to indicate a point in time, not an interval or duration. Wouldn't it make sense to store their work hours in two distinct columns, StartTime and EndTime?
In order to sum up the working hours for an employee you can calculate the difference between the shift start time and end time in minutes and convert it to readable format as following:
DECLARE #StartTime datetime = '08:00'
DECLARE #EndTime datetime = '10:47'
DECLARE #durMinutes int
DECLARE #duration nvarchar(5)
SET #durMinutes = DATEDIFF(MINUTE, #StartTime, #EndTime)
SET #duration =
(SELECT RIGHT('00' + CAST((#durMinutes / 60) AS VARCHAR(2)),2) + ':' +
RIGHT('00' + CAST((#durMinutes % 60) AS VARCHAR(2)), 2))
SELECT #duration
The result : 02:47
two hours and 47 minutes
select DATEDIFF(MINUTE, '0:00:00', '00:02:08')
results in :- 2
select DATEDIFF(SECOND, '0:00:00', '00:02:08')
results in :- 128
Using seconds gives a better answer.
So I think the answer can be
SELECT
EmployeeId
, seconds_worked = SUM (DATEDIFF (SECOND, '0:00:00', WrkHrs))
FROM
tbl_employee
GROUP BY
EmployeeId;
DECLARE #Tab TABLE
(
data CHAR(5)
)
INSERT #Tab
SELECT '25:30' UNION ALL
SELECT '31:45' UNION ALL
SELECT '16:00'
SELECT STUFF(CONVERT(CHAR(8), DATEADD(SECOND, theHours + theMinutes,
'19000101'), 8), 1, 2, CAST((theHours + theMinutes) / 3600 AS VARCHAR(12)))
FROM (
SELECT ABS(SUM(CASE CHARINDEX(':', data) WHEN 0 THEN 0 ELSE 3600 *
LEFT(data, CHARINDEX(':', data) - 1) END)) AS theHours,
ABS(SUM(CASE CHARINDEX(':', data) WHEN 0 THEN 0 ELSE 60 *
SUBSTRING(data, CHARINDEX(':', data) + 1, 2) END)) AS theMinutes
FROM #Tab
) AS d
For MS SQL Server, when your WorkingTime is stored as a time, or a varchar in order to sum it up you should consider that:
1) Time format is not supporting sum, so you need to parse it
2) 23:59:59.9999999 is the maximum value for the time.
So, the code that will work to get you the total number of WorkingHours:WorkingMinutes:WorkingSeconds would be the following:
SELECT
CAST(FORMAT((SUM((DATEPART("ss",WorkingTime) + DATEPART("mi",WorkingTime) * 60 + DATEPART("hh",WorkingTime) * 3600)) / 3600),'00') as varchar(max)) + ':' +
CAST(FORMAT((SUM((DATEPART("ss",WorkingTime) + DATEPART("mi",WorkingTime) * 60 + DATEPART("hh",WorkingTime) * 3600)) % 3600 / 60),'00') as varchar(max)) + ':' +
CAST(FORMAT((SUM((DATEPART("ss",WorkingTime) + DATEPART("mi",WorkingTime) * 60 + DATEPART("hh",WorkingTime) * 3600)) % 3600 % 60),'00') as varchar(max)) as WorkingTimeSum
FROM TableName
It must be as simple as that.
Steps
convert time to seconds
sum the RESULT
convert the sum to time
Eg:
take a case you might want to sum the following time:
| present_hours |
|-----------------|
| 00:01:20.000000 |
|-----------------|
| 00:01:13.000000 |
|-----------------|
| 00:01:45.000000 |
|-----------------|
| 00:01:03.000000 |
|-----------------|
| 00:01:10.000000 |
|-----------------|
| 00:00:56.000000 |
SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(present_hours))) as total_present_hours FROM time_booking;

SUM of elapsed time gathered from multiple rows

I am trying to show my team's productivity vs non-productivity percentages based of what type of work they perform throughout the day. I can successfully achieve the format i am looking for with the below code but if an associate is productive in 2 separate departments in 1 day the sub-query fails because it returns multiple rows.
This is what im working with now
DECLARE
#Offset INT ,
#Start DATETIME ,
#Loc INT ,
#NON time(0) ,
#PROD time(0) ,
#TOTAL TIME(0)
SET #Offset = 4
SET #Start = dateadd(day, datediff(day, 0, getdate()), -#Offset)
--SUM OF ALL DEPT CATEGORIES WORKED FOR SELECTED DATE RANGE
select Codes = (DeptCode + ' ' + Opcode)
, TimeSum = right(convert(varchar(9),(sum(datediff(second,StartTime,FinishTime)) / 3600 )),3) + ':' + right('0' + convert(varchar(2),(sum(datediff(second,StartTime,FinishTime)) / 60) % 60 ),2)
, Units = sum(units)
FROM TimeLogNEW
where EventDate = #Start and Location = 10 and ID = 2372013
group by EventDate, id, DeptCode, OpCode
--SUM OF NON PRODUCTIVE HOURS WORKED (HAVING A UNITS SUM OF '0' IS CONSIDERED NON PRODUCTIVE) --NOT INCLUDING 'LL' (WHICH IS A LUNCH PERIOD)
set #NON =
(select NonProd = right(convert(varchar(9),(sum(datediff(second,'0:00:00',TimeSum)) / 3600 )),3) + ':' + right('0' + convert(varchar(2),(sum(datediff(second,'0:00:00',TimeSum)) / 60) % 60 ),2)
from (select
TimeSum = right(convert(varchar(9),(sum(datediff(second,m.StartTime,m.FinishTime)) / 3600 )),3) + ':' + right('0' + convert(varchar(2),(sum(datediff(second,m.StartTime,m.FinishTime)) / 60) % 60 ),2)
,Units = sum(m.units)
FROM TimeLogNEW m
where m.EventDate = #Start and opCode Not in ('ll') and m.Location = 10 and m.ID = 2372013
group by m.EventDate, m.id, m.DeptCode, m.OpCode
)t Group By Units Having Units = 0)
select #NON as 'NON-PROD_Hours'
--SUM OF PRODUCTIVE HOURS WORKED (HAVING A UNITS SUM OF MORE THAN '0' IS CONSIDERED PRODUCTIVE) --NOT INCLUDING 'LL' (WHICH IS A LUNCH PERIOD)
set #PROD =
(select TotalProd = right(convert(varchar(9),(sum(datediff(second,'0:00:00',TimeSum)) / 3600 )),3) + ':' + right('0' + convert(varchar(2),(sum(datediff(second,'0:00:00',TimeSum)) / 60) % 60 ),2)
from (select
TimeSum = right(convert(varchar(9),(sum(datediff(second,m.StartTime,m.FinishTime)) / 3600 )),3) + ':' + right('0' + convert(varchar(2),(sum(datediff(second,m.StartTime,m.FinishTime)) / 60) % 60 ),2)
,Units = sum(m.units)
FROM TimeLogNEW m
where m.EventDate = #Start and opCode Not in ('ll') and m.Location = 10 and m.ID = 2372013
group by m.EventDate, m.id, m.DeptCode, m.OpCode
)t Group By Units Having Units >0 )
select #PROD as 'PROD_Hours'
--SUM OF ALL HOURS WORKED --NOT INCLUDING 'LL' (WHICH IS A LUNCH PERIOD)
set #TOTAL =
(select
TotalTime_NoLunch = right(convert(varchar(9),(sum(datediff(second,StartTime,FinishTime)) / 3600 )),3) + ':' + right('0' + convert(varchar(2),(sum(datediff(second,StartTime,FinishTime)) / 60) % 60 ),2)
FROM TimeLogNEW
where EventDate = #Start and ID = 2372013 and OpCode not in ('ll'))
select #TOTAL as 'SUM_Hours'
--PERCENTAGE OF PRODUCTIVITY
select
[Prod%] =convert(varchar(30),(100 *datediff(minute,'0:00:00',#PROD)/datediff(minute,'0:00:00',#TOTAL) )) +'%'
--PERCENTAGE OF NON-PRODUCTIVITY
select
[NON Prod%] =convert(varchar(30),(100 *datediff(minute,'0:00:00',#NON)/datediff(minute,'0:00:00',#TOTAL) )) +'%'
Result shown. For 7-2-18
If more than 1 of the dept categories codes has greater than 0 Units the sub-query fails. I have been trying to re-arrange the query to allow the grouping of sums equaling 0 and sums having greater than 0, but am stumped here. I am not getting correct results when ungrouping the Units column in the sub.
Here is what the raw data looks like with more than 1 productive operation. 7-3-18
The problem is that you group by DeptCode and OpCode but do not sum these results over the groups. Try this:
DECLARE
#Offset INT ,
#Start DATETIME ,
#Loc INT = 10 ,
#NON INT ,
#PROD INT ,
#TOTAL INT
SET #Offset = 4;
SET #Start = DATEADD(day, DATEDIFF(day, 0, GETDATE()), -#Offset);
--SUM OF ALL DEPT CATEGORIES WORKED FOR SELECTED DATE RANGE
WITH
TimeLog (EventDate, [Location], ID, DeptCode, OpCode, Units, Seconds) AS (
SELECT EventDate, [Location], ID, DeptCode, OpCode, SUM(Units)
, SUM(DATEDIFF(second, StartTime, FinishTime))
FROM TimeLogNEW
GROUP BY EventDate, [Location], ID, DeptCode, OpCode
)
SELECT
Codes = (DeptCode + ' ' + Opcode)
, TimeSum = CAST(DATEADD(second, Seconds, 0) AS time(0))
, Units
FROM TimeLog
WHERE EventDate = #Start AND [Location] = #Loc AND ID = 2372013;
WITH
TimeLog (EventDate, [Location], ID, DeptCode, OpCode, Units, Seconds) AS (
SELECT EventDate, [Location], ID, DeptCode, OpCode, SUM(Units)
, SUM(DATEDIFF(second, StartTime, FinishTime))
FROM TimeLogNEW
GROUP BY EventDate, [Location], ID, DeptCode, OpCode
),
TimeSplit (EventDate, Loc, ID, DC, OC, Units, Seconds, NON_PROD, PROD) AS (
SELECT EventDate, [Location], ID, DeptCode, OpCode, Units, Seconds
, CASE WHEN Units = 0 THEN Seconds ELSE 0 END
, CASE WHEN Units > 0 THEN Seconds ELSE 0 END
FROM TimeLog
)
SELECT #NON = SUM(NON_PROD), #PROD = SUM(PROD), #TOTAL = SUM(Seconds)
FROM TimeSplit
WHERE EventDate = #Start AND Loc = #Loc AND ID = 2372013 AND OC NOT IN ('LL');
-- RESULTS
SELECT
CONVERT(nvarchar(30), #NON/3600) + RIGHT(CONVERT(nvarchar(8), DATEADD(second, #NON, 0), 108), 6) AS 'NON-PROD_Hours',
CONVERT(nvarchar(30), #PROD/3600) + RIGHT(CONVERT(nvarchar(8), DATEADD(second, #PROD, 0), 108), 6) AS 'PROD_Hours',
CONVERT(nvarchar(30), #TOTAL/3600) + RIGHT(CONVERT(nvarchar(8), DATEADD(second, #TOTAL, 0), 108), 6) AS 'SUM_Hours',
CAST(100.0 * #PROD / #TOTAL AS varchar(30)) +'%' AS 'Prod%',
CAST(100.0 * #NON / #TOTAL AS varchar(30)) +'%' AS 'NON Prod%';

Random days in date or datetime

Is it possible to random only days in date or Datetime within a range of days in sql server, t-sql.
For example if dates have days between 1to15 i want to randomise days creating a day number between 16 and 30. Example: 2017-7-10 to 2017-7-21(random day within 16to30). Thank you
DECLARE #dateA DATE = '2017-07-10'
DECLARE #dateB DATE
IF day(#dateA) < 16 --day number between 1 and 15
SET #dateB = DATEFROMPARTS(year(#dateA), month(#dateA), FLOOR(RAND() * (30 - 16) + 16))
SELECT #dateA, #dateb
DATEFROMPARTE SQL Server 2012+
No version specific:
DECLARE #dateA DATE = '2017-07-10'
DECLARE #dateB DATE
DECLARE #day INT
IF day(#dateA) < 16 --day number between 1 and 15
BEGIN
SET #day = day(#dateA)
SET #dateB = dateadd(day, - 1 * #day + FLOOR(RAND() * (30 - 16) + 16), #dateA)
END
SELECT #dateA, #dateb
New request:
UPDATE yourTable
SET yourDateOrDatetimeColumn = dateadd(day, - 1 * day(yourDateOrDatetimeColumn) + FLOOR(RAND() * (30 - 16) + 16), yourDateOrDatetimeColumn)
WHERE day(yourDateOrDatetimeColumn) < 16
SELECT RandomDate16To30DaysFromToday = DATEADD(DAY, FLOOR(RAND()*(30-16)+16), GETDATE())

Find records between two Quarters in SQL Server?

I want to find records between two-quarters of different years in SQL Server.
SELECT ('Q'+cast(DATEPART(QUARTER,calldate) as varchar(3))+'-'+cast(YEAR(calldate) as varchar(4)))
period,providerid,volume as volume,type
FROM table V
where DATEPART(QUARTER,calldate) between #Q1 and #Q2 and
datepart(year,calldate) in (#Y1,#Y2) and providerid=#carrierID
Here Q1=4 and Q2=3 and #Y1=2014,#Y2=2016
Now,I have only records from Q2-2016, So it should return available records
but I am getting blank rows.
if I change the parameter like this
Here Q1=3 and Q2=4 and #Y1=2014,#Y2=2016 then i am getting records.
I want all records between these two-quarters like (Q3-2014 and Q2-2016).?
Here is one method:
where datename(year, calldate) + datename(quarter, calldate)
between #Y1 + #Q1 and #Y2 + #Q2;
This assumes that the variables are actually strings. You could also do this using numbers:
where datepart(year, calldate) * 10 + datename(quarter, calldate)
between #Y1 * 10 + #Q1 and #Y2 * 10 + #Q2;
And, here is a way that would use indexes:
where calldate >= datefromparts(#Y1, #Q1*3 - 2, 1) and
calldate < (case when #Q2 = 4
then datefromparts(#Y2 + 1, 1, 1)
else datefromparts(#Y2, #Q2*3 - 2 + 3, 1)
end)
could try something like this
SELECT
('Q'+cast(DATEPART(QUARTER,calldate) as varchar(3))+'-'+cast(YEAR(calldate) as varchar(4)))
period,providerid,volume as volume,type
FROM table V
where DATEPART(QUARTER,calldate) + datepart(year,calldate) *4 between #Q1 + #Y1 * 4 and #Q2 + #Y2 * 4

How to sum up time field in SQL Server

I have a column called "WrkHrs" and the data type is time(hh:mm:ss). I want to sum up the working hours for employees. But since it's time data type sql server doesn't let me use like sum(columnname).
How can I sum up the time data type fieled in sql query?
SELECT EmployeeID, minutes_worked = SUM(DATEDIFF(MINUTE, '0:00:00', WrkHrs))
FROM dbo.table
-- WHERE ...
GROUP BY EmployeeID;
You can format it pretty on the front end. Or in T-SQL:
;WITH w(e, mw) AS
(
SELECT EmployeeID, SUM(DATEDIFF(MINUTE, '0:00:00', WrkHrs))
FROM dbo.table
-- WHERE ...
GROUP BY EmployeeID
)
SELECT EmployeeID = e,
WrkHrs = RTRIM(mw/60) + ':' + RIGHT('0' + RTRIM(mw%60),2)
FROM w;
However, you're using the wrong data type. TIME is used to indicate a point in time, not an interval or duration. Wouldn't it make sense to store their work hours in two distinct columns, StartTime and EndTime?
In order to sum up the working hours for an employee you can calculate the difference between the shift start time and end time in minutes and convert it to readable format as following:
DECLARE #StartTime datetime = '08:00'
DECLARE #EndTime datetime = '10:47'
DECLARE #durMinutes int
DECLARE #duration nvarchar(5)
SET #durMinutes = DATEDIFF(MINUTE, #StartTime, #EndTime)
SET #duration =
(SELECT RIGHT('00' + CAST((#durMinutes / 60) AS VARCHAR(2)),2) + ':' +
RIGHT('00' + CAST((#durMinutes % 60) AS VARCHAR(2)), 2))
SELECT #duration
The result : 02:47
two hours and 47 minutes
select DATEDIFF(MINUTE, '0:00:00', '00:02:08')
results in :- 2
select DATEDIFF(SECOND, '0:00:00', '00:02:08')
results in :- 128
Using seconds gives a better answer.
So I think the answer can be
SELECT
EmployeeId
, seconds_worked = SUM (DATEDIFF (SECOND, '0:00:00', WrkHrs))
FROM
tbl_employee
GROUP BY
EmployeeId;
DECLARE #Tab TABLE
(
data CHAR(5)
)
INSERT #Tab
SELECT '25:30' UNION ALL
SELECT '31:45' UNION ALL
SELECT '16:00'
SELECT STUFF(CONVERT(CHAR(8), DATEADD(SECOND, theHours + theMinutes,
'19000101'), 8), 1, 2, CAST((theHours + theMinutes) / 3600 AS VARCHAR(12)))
FROM (
SELECT ABS(SUM(CASE CHARINDEX(':', data) WHEN 0 THEN 0 ELSE 3600 *
LEFT(data, CHARINDEX(':', data) - 1) END)) AS theHours,
ABS(SUM(CASE CHARINDEX(':', data) WHEN 0 THEN 0 ELSE 60 *
SUBSTRING(data, CHARINDEX(':', data) + 1, 2) END)) AS theMinutes
FROM #Tab
) AS d
For MS SQL Server, when your WorkingTime is stored as a time, or a varchar in order to sum it up you should consider that:
1) Time format is not supporting sum, so you need to parse it
2) 23:59:59.9999999 is the maximum value for the time.
So, the code that will work to get you the total number of WorkingHours:WorkingMinutes:WorkingSeconds would be the following:
SELECT
CAST(FORMAT((SUM((DATEPART("ss",WorkingTime) + DATEPART("mi",WorkingTime) * 60 + DATEPART("hh",WorkingTime) * 3600)) / 3600),'00') as varchar(max)) + ':' +
CAST(FORMAT((SUM((DATEPART("ss",WorkingTime) + DATEPART("mi",WorkingTime) * 60 + DATEPART("hh",WorkingTime) * 3600)) % 3600 / 60),'00') as varchar(max)) + ':' +
CAST(FORMAT((SUM((DATEPART("ss",WorkingTime) + DATEPART("mi",WorkingTime) * 60 + DATEPART("hh",WorkingTime) * 3600)) % 3600 % 60),'00') as varchar(max)) as WorkingTimeSum
FROM TableName
It must be as simple as that.
Steps
convert time to seconds
sum the RESULT
convert the sum to time
Eg:
take a case you might want to sum the following time:
| present_hours |
|-----------------|
| 00:01:20.000000 |
|-----------------|
| 00:01:13.000000 |
|-----------------|
| 00:01:45.000000 |
|-----------------|
| 00:01:03.000000 |
|-----------------|
| 00:01:10.000000 |
|-----------------|
| 00:00:56.000000 |
SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(present_hours))) as total_present_hours FROM time_booking;