Insert value into column using function and mathematical calculation - sql

table IssuedBooks
{
column RollNo,BookNo,BookName,AuthorName,IssueDate,Fine
}
I want to create a function which fills or gives the calculated Fine when called. Suppose after 15 days of IssueDate there is a fine of 5 each day. May be I can send the IssueDate as parameter to the function and then calculate the difference between the IssueDate and Current date using DATEDIFF(DAY,IssueDate,CAST(GETDATE() as date)) and then use the number of days returned to check whether they are greater than 15 and calculate the fine accordingly and return it through function.I am very confused about how to implement it, what will be the queries etc. Please help.
Thank you very much in advance..

SELECT
RollNo, BookNo, BookName, AuthorName, IssueDate,
CASE
WHEN DATEDIFF(Day,IssueDate,cast(getdate() as date)) > 15
THEN (DATEDIFF(Day,IssueDate,cast(getdate() as date)) - 15) * 5
ELSE '0'
END as Fine
From IssuedBooks
Or just:
UPDATE IssuedBooks
SET Fine = (DATEDIFF(Day,IssueDate,cast(getdate() as date)) - 15) * 5
WHERE DATEDIFF(Day,IssueDate,cast(getdate() as date)) > 15

Related

SQL - Find value for the last 5 weeks and the next 5 weeks in the same query

I need to find inventory values for the last 5 weeks and the next 5 weeks on any given day I run the query (going to connect to Excel and run daily).
I am able to find them individually but when done together I get no returns.
The following work individually, is there a way to combine and get all returns?
Select * FROM Table
WHERE vdvInventory.Count >= CAST(DATEADD(WEEK, -5, GETDATE()) as DATE)
alternatively
Select * FROM Table
WHERE DATEDIFF(WEEK,vdvInventory.Count,GETDATE() )<5
If I try adding both where statements into one with an ADD I get no returns.
For Example:
Select * FROM Table
WHERE DATEDIFF(WEEK,vdvInventory.Count,GETDATE() )<5
AND DATEDIFF(WEEK,vdvInventory.Count,GETDATE() )>5
Thanks for any help or guidance with this!
Your query doesn't work because you have a contradictory statement: same expression (DATEDIFF(WEEK,vdvInventory.Count,GETDATE())) cannot be less and greater than 5 at the same time.
Try instead the following:
Select * FROM Table
WHERE vdvInventory.Count >= CAST(DATEADD(WEEK, -5, GETDATE()) as DATE)
and vdvInventory.Count <= CAST(DATEADD(WEEK, 5, GETDATE()) as DATE)

In Microsoft SQL Server, how to split rows using datetime data

As I am working on a project for my university, I am supposed to create a dashboard for machines downtime.
Every time that a machine is down during the day, the availability is calculated as [ 24 (hours) - Downtime / 24 (hours) ].
However, there are some situations where the machines are down more than 1 day, so it means that I have the split the number of hours that machine is down and distributed to the respective days.
Here is what the data looks like:
Here is what the result looks like:
My idea,
Create one temp table with number between specific range by SELECT DISTINCT SeqDateDiff = number FROM master..[spt_values] WHERE number BETWEEN 0 AND 1000.
PS: the range is 0 to 1000 in the sample, you can create wider range, but it should not be neccessary, you can consider remove the machine if already down over 1000 days. And there are some other methods to create this kind of range table, you can google it.
Then left join with your table with date difference by on target.DateDiff+1>seq.SeqDateDiff.
Then the rest is simple, just calculate out reported/completed based on different situations.
Check working sample at SQL fiddler.
Below is the codes:
select ServiceID,
case when SeqDateDiff>0 then cast(DATEADD(day, SeqDateDiff, Reported) As Date) else Reported end Started,
case when SeqDateDiff=DateDiff
then Completed
else DATEADD(second, -1, cast(cast(DATEADD(day, SeqDateDiff+1, Reported) As Date) as DateTime))
end Completed,
DateDiff, SeqDateDiff
from (select ServiceID, Completed, Reported, DATEDIFF(day, Reported, Completed) DateDiff from YourTable) target
left join (
SELECT DISTINCT SeqDateDiff = number FROM master..[spt_values] WHERE number BETWEEN 0 AND 1000
) seq on target.DateDiff+1>seq.SeqDateDiff
select case when datediff(hh, reported, completed)>12 then 12 else
datediff(hh, reported, completed) end from yourtable
if day(reported)<>day(completed)
begin
select datediff(hh, cast(completed as date), completed) from yourtable
end
Assuming it's never down more than 2 days. If so, adjust logic accordingly...

Querying result from select part of statement

I have a stored procedure to work out how many working days between two dates
select
casekey, LoginName, casestartdatedate,
dbo.CalcWorkDaysBetween(casestartdatedate, GETDATE()) AS 'WD'
from
Car_case with (nolock)
where
dbo.CalcWorkDaysBetween(casestartdatedate, GETDATE()) <= DATEADD(dd,DATEDIFF(dd, 0, GETDATE()), -60)
and CaseClosedDateDate is null
order by
CaseStartDateDate asc
In my select part of statement I want to show the number of working days between the case start date and today's date. This part is fine. But I only want to return cases where the 'working days' is 60 days or greater - I'm having trouble with this part of query. See my code above. not too sure why its not working. It's returning results less than and greater than 60 days making me realize I've gone wrong somewhere.
Any help would be appreciated!
If I understand correctly, you just need to fix the where condition:
select casekey, LoginName, casestartdatedate,
dbo.CalcWorkDaysBetween(casestartdatedate, GETDATE()) AS WD
from Car_case cc with (nolock)
where dbo.CalcWorkDaysBetween(casestartdatedate, GETDATE()) >= 60 and
CaseClosedDateDate is null
order by CaseStartDateDate asc;
Note: In your version you are comparing the result of the function (which is presumably an integer) to a date.

Not getting actual minutes in SQL DateDiff

I searched in different places and found below queries. I am using the following queries to get the actual minutes difference in SQL. The dates I provide are the same day. I need difference in minutes only but SQL is returning 35 instead of 5 minutes in the first query. And the second query return milliseconds.
SELECT DATEDIFF(MINUTE,GETDATE(), CONVERT(datetime,'2016-08-11 16:04:24'))%3600/60 AS MinuteDiff
SELECT datediff(minute,GETDATE(), CONVERT(datetime,'2016-08-11 16:04:24')) as MinutesDiff
What is missing. Please help.
I need to put a condition that if time is less than 20 minutes then
do this
else
do this
Updated:
The issue occurs when i use GetDate(). When I use a fix date it works fine
You need to place the GETDATE() after your datetime value, other wise in your case you will get the minutes in negative value.
SELECT DATEDIFF(MINUTE,CONVERT(datetime,'2016-08-11 16:04:24'), GETDATE()) AS MinuteDiff
The current GETDATE() is 2016-08-11 17:05:39.053, so it returns 61.
Then based on the value, using IF ... ELSE ... you can do your expected operation:
IF DATEDIFF(MINUTE,CONVERT(datetime,'2016-08-11 16:04:24'), GETDATE()) < 20
PRINT 'With in 20 mins'
ELSE
PRINT 'More than 20 mins'
Here is a working example of what your after...although you probably need to switch out the date components as appropriate for your usage.
select
case
when
(SELECT datediff(minute,GETDATE(), CONVERT(datetime,'2016-08-11 06:00:00'))) < 20 then
(select 'do this')
else
(select 'do something else')
end as answer
If you want minute span between two datetime, then your second one is enough.
SELECT datediff(n, CONVERT(datetime,'2016-08-11 16:04:24'),GETDATE()) as MinutesDiff
you can use CASE for your further
select
case when
datediff(n, CONVERT(datetime,'2016-08-11 16:04:24'),GETDATE()) < 20 then
`your code`
else
`your else code`
end minte
Hey sorry for the initial poor explanation.
I use something like the following frequently this will return a INT and decide if it's then you can do the logic on it, equal to, not equal less than greater than etc.
If it is true it will return a 1 or it is false a 0. You can get it to return columns or set it to a string.
Hope it helps
select
Case
When DateDiff(minute,[column],Getdate()) > 20 then 1 else 0
end as [alias]

Group DateTime into 5,15,30 and 60 minute intervals

I am trying to group some records into 5-, 15-, 30- and 60-minute intervals:
SELECT AVG(value) as "AvgValue",
sample_date/(5*60) as "TimeFive"
FROM DATA
WHERE id = 123 AND sample_date >= 3/21/2012
i want to run several queries, each would group my average values into the desired time increments. So the 5-min query would return results like this:
AvgValue TimeFive
6.90 1995-01-01 00:05:00
7.15 1995-01-01 00:10:00
8.25 1995-01-01 00:15:00
The 30-min query would result in this:
AvgValue TimeThirty
6.95 1995-01-01 00:30:00
7.40 1995-01-01 01:00:00
The datetime column is in yyyy-mm-dd hh:mm:ss format
I am getting implicit conversion errors of my datetime column. Any help is much appreciated!
Using
datediff(minute, '1990-01-01T00:00:00', yourDatetime)
will give you the number of minutes since 1990-1-1 (you can use the desired base date).
Then you can divide by 5, 15, 30 or 60, and group by the result of this division.
I've cheked it will be evaluated as an integer division, so you'll get an integer number you can use to group by.
i.e.
group by datediff(minute, '1990-01-01T00:00:00', yourDatetime) /5
UPDATE As the original question was edited to require the data to be shown in date-time format after the grouping, I've added this simple query that will do what the OP wants:
-- This convert the period to date-time format
SELECT
-- note the 5, the "minute", and the starting point to convert the
-- period back to original time
DATEADD(minute, AP.FiveMinutesPeriod * 5, '2010-01-01T00:00:00') AS Period,
AP.AvgValue
FROM
-- this groups by the period and gets the average
(SELECT
P.FiveMinutesPeriod,
AVG(P.Value) AS AvgValue
FROM
-- This calculates the period (five minutes in this instance)
(SELECT
-- note the division by 5 and the "minute" to build the 5 minute periods
-- the '2010-01-01T00:00:00' is the starting point for the periods
datediff(minute, '2010-01-01T00:00:00', T.Time)/5 AS FiveMinutesPeriod,
T.Value
FROM Test T) AS P
GROUP BY P.FiveMinutesPeriod) AP
NOTE: I've divided this in 3 subqueries for clarity. You should read it from inside out. It could, of course, be written as a single, compact query
NOTE: if you change the period and the starting date-time you can get any interval you need, like weeks starting from a given day, or whatever you can need
If you want to generate test data for this query use this:
CREATE TABLE Test
( Id INT IDENTITY PRIMARY KEY,
Time DATETIME,
Value FLOAT)
INSERT INTO Test(Time, Value) VALUES('2012-03-22T00:00:22', 10)
INSERT INTO Test(Time, Value) VALUES('2012-03-22T00:03:22', 10)
INSERT INTO Test(Time, Value) VALUES('2012-03-22T00:04:45', 10)
INSERT INTO Test(Time, Value) VALUES('2012-03-22T00:07:21', 20)
INSERT INTO Test(Time, Value) VALUES('2012-03-22T00:10:25', 30)
INSERT INTO Test(Time, Value) VALUES('2012-03-22T00:11:22', 30)
INSERT INTO Test(Time, Value) VALUES('2012-03-22T00:14:47', 30)
The result of executing the query is this:
Period AvgValue
2012-03-22 00:00:00.000 10
2012-03-22 00:05:00.000 20
2012-03-22 00:10:00.000 30
Building on #JotaBe's answer (to which I cannot comment on--otherwise I would), you could also try something like this which would not require a subquery.
SELECT
AVG(value) AS 'AvgValue',
-- Add the rounded seconds back onto epoch to get rounded time
DATEADD(
MINUTE,
(DATEDIFF(MINUTE, '1990-01-01T00:00:00', your_date) / 30) * 30,
'1990-01-01T00:00:00'
) AS 'TimeThirty'
FROM YourTable
-- WHERE your_date > some max lookback period
GROUP BY
(DATEDIFF(MINUTE, '1990-01-01T00:00:00', your_date) / 30)
This change removes temp tables and subqueries. It uses the same core logic for grouping by 30 minute intervals but, when presenting the data back as part of the result I'm just reversing the interval calculation to get the rounded date & time.
So, in case you googled this, but you need to do it in mysql, which was my case:
In MySQL you can do
GROUP BY
CONCAT(
DATE_FORMAT(`timestamp`,'%m-%d-%Y %H:'),
FLOOR(DATE_FORMAT(`timestamp`,'%i')/5)*5
)
In the new SQL Server 2022, you can use DATE_BUCKET, this rounds it down to the nearest interval specified.
SELECT
DATE_BUCKET(minute, 5, d.sample_date) AS TimeFive,
AVG(d.value) AS AvgValue
FROM DATA d
WHERE d.id = 123
AND d.sample_date >= '20121203'
GROUP BY
DATE_BUCKET(minute, 5, d.sample_date);
You can use the following statement, this removed the second component and calculates the number of minutes away from the five minute mark and uses this to round down to the time block. This is ideal if you want to change your window, you can simply change the mod value.
select dateadd(minute, - datepart(minute, [YOURDATE]) % 5, dateadd(minute, datediff(minute, 0, [YOURDATE]), 0)) as [TimeBlock]
This will help exactly what you want
replace dt - your datetime c - call field astro_transit1 - your table 300 refer 5 min so add 300 each time for time gap increase
SELECT FROM_UNIXTIME( 300 * ROUND( UNIX_TIMESTAMP( r.dt ) /300 ) ) AS 5datetime, ( SELECT r.c FROM astro_transit1 ra WHERE ra.dt = r.dt ORDER BY ra.dt DESC LIMIT 1 ) AS first_val FROM astro_transit1 r GROUP BY UNIX_TIMESTAMP( r.dt ) DIV 300 LIMIT 0 , 30