update SQL statement and using if exists - sql

I am trying to select a value from one table and insert it into a specfic section of another table. I have the following sql (mssql 2008)
if exists (select datesubmitted from JADHist where datesubmitted = DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()-1)))
Begin
Select JadOPNTotal from JADhist where dateSubmitted = DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()-1))
end
else
begin
Select jadopntotal from JADhist where dateSubmitted = DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()-2))
end
This always retrieves one value with datatype real. I have another table which is 2 columns, one is the date with the hour next to it and there is an entry for the next 2 weeks for every hour. The format is 2013-03-26 01:00:00.000 and so on. I want to insert the value I get from the code above into the 2nd table for one 24 hour period (24 entries). THe 24 period will be today from 6am till tomorrow at 6am.
I also have the following code with a test value of 10 in it just to prove the code updates opndata correctly.
UPDATE [GasNominations].[dbo].[OPNData]
SET
[Value] = '10'
WHERE NomSubmittedDate between DATEADD(HH, 6, DATEDIFF(dd, 0, GETDATE()))
and DATEADD(HH, 5, DATEDIFF(dd, 0, GETDATE()+1))
GO
I want to replace the '10' value with the if exists statement but I cant get the syntax correct.

try this
declare #total varchar(10)
if exists (select datesubmitted from JADHist
where datesubmitted = DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()-1)))
Begin
Select #total = JadOPNTotal from JADhist
where dateSubmitted = DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()-1))
end
else
begin
Select #total = jadopntotal from JADhist
where dateSubmitted = DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()-2))
end
UPDATE [GasNominations].[dbo].[OPNData]
SET
[Value] = #total
WHERE NomSubmittedDate between DATEADD(HH, 6, DATEDIFF(dd, 0, GETDATE()))
and DATEADD(HH, 5, DATEDIFF(dd, 0, GETDATE()+1))
GO

Related

Assigning an input value to a column's value in SQL Server stored procedure

I am trying to write a stored procedure that will take a date as input.
If the date passed is 18-07-2019, then data from 17-07-2019 06:00 am till 18-07-2019 06:00 am should be fetched from the database.
In the below stored procedure, I am taking Reportdate (datetime datatype) as the input. But I am unable to assign it to the column which contains the time (TimestampUTC column) in the database table that I am querying.
So as per the below logic, data is shown automatically from yesterday to today '(21-07-2019 to 22-07-2019)` and doesn't change based on the date entered by the user.
Showing part of the stored procedure here:
CREATE PROCEDURE [dbo].[GetElectricityData]
#Reportdate DATETIME
AS
BEGIN
SET NOCOUNT ON;
WITH t AS
(
SELECT a.name, b.Data , a.UnitId, b.TimestampUTC
FROM [10.87.233.57,1433].[EMMA].[dbo].MeterTags a
JOIN [10.87.233.57,1433].[EMMA].[dbo].[DataLog] b ON a.MeterTagId = b.MeterTagId
WHERE b.MeterTagId IN (388, 184, 196, 194, 197)
AND TimestampUTC BETWEEN DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE() - 1), 0) + '06:00'
AND DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0) + '06:00'
GROUP BY
DATEADD(minute, DATEDIFF(minute, 0, TimestampUTC) / 15 * 15, 0),
a.name, b.Data, a.UnitId, b.TimestampUTC
)
Any suggestions will be hugely helpful.
GETDATE() will always give you the current date this is the reason why the data is shown automatically from yesterday to today instead try something like below
DATEADD(DAY, DATEDIFF(DAY, 0, CONVERT(datetime, #ReportDate) - 1), 0) + '06:00'
AND
DATEADD(DAY, DATEDIFF(DAY, 0, CONVERT(datetime, #ReportDate)), 0) + '06:00'
I can see that you are referencing GETDATE() in the WHERE clause (twice). Replace them with your #Reportdate variable as per below.
CREATE PROCEDURE [dbo].[GetElectricityData]
#Reportdate DATETIME
AS
BEGIN
SET NOCOUNT ON;
WITH t AS
(
SELECT a.name, b.Data , a.UnitId, b.TimestampUTC
FROM [10.87.233.57,1433].[EMMA].[dbo].MeterTags a
JOIN [10.87.233.57,1433].[EMMA].[dbo].[DataLog] b ON a.MeterTagId = b.MeterTagId
WHERE b.MeterTagId IN (388, 184, 196, 194, 197)
AND TimestampUTC BETWEEN DATEADD(DAY, DATEDIFF(DAY, 0, #Reportdate - 1), 0) + '06:00'
AND DATEADD(DAY, DATEDIFF(DAY, 0, #Reportdate), 0) + '06:00'
GROUP BY
DATEADD(minute, DATEDIFF(minute, 0, TimestampUTC) / 15 * 15, 0),
a.name, b.Data, a.UnitId, b.TimestampUTC
)

DATEADD MS -1 does nothing

This is my basic "test"
select DATEADD(ms,-2,DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0))
, DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0)
,case when DATEADD(ms,-2,DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0)) != DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0) then 'No Match' else 'Match' end
union all
select DATEADD(ms,-1,DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0))
,DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0)
,case when DATEADD(ms,-1,DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0)) != DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0) then 'No Match' else 'Match' end
I am trying to understand why MS -2 , subtracts 3 and MS -1 subtracts none.
MSSQL's datetime data type has a finest granularity of .00333333s (repeating), or roughly 3 milliseconds. Changes less than that will result in either no change, or rounded to 3.
From https://msdn.microsoft.com/en-us/library/cc280460.aspx
datetime2(3) has a precision of one millisecond, and datetime has a
precision of 1/300 of a second.

SQL: How to get the following day from end of the month

Example:
If I run this query today (26 January), my result will be addedon +1 day which is 27 January.
select addedon
from member
Where Day(addedon) = Day(DateAdd(dd, 1, GetDate()))
and Month(addedon) = Month(DateAdd(dd, 1, GetDate()))
However, when I run this query on 31 January, it is giving me 1 January result instead of 1 Feb.
Please help! Note that I can only use simple select statement (like the above) in my application.
To get the beginning of the next month:
SELECT DATEADD(MM, DATEDIFF(MM, 0, GETDATE()) + 1, 0)
This will return member whose addedon falls on the first day of the next month.
SELECT addedon
FROM member
WHERE
addedon >= DATEADD(MM, DATEDIFF(MM, 0, GETDATE()) + 1, 0)
AND addedon < DATEADD(DD, 1, DATEADD(MM, DATEDIFF(MM, 0, GETDATE()) + 1, 0))
This will return member whose addedonfalls on the next day:
SELECT addedon
FROM #member
WHERE
addedon >= DATEADD(DD, DATEDIFF(DD, 0, GETDATE()) + 1, 0)
AND addedon < DATEADD(DD, DATEDIFF(DD, 0, GETDATE()) + 2, 0)
I'm going to guess that your datetime are - as is pretty typical - stored in your database as UTC datetime, and that you are somewhere in the Western Hemisphere, and that calling Month on a UTC time after, say, 9:30EDT (or 8:30CDT) is returning 2, matching Month(DateAdd(dd, 1, GetDate())).
Most of the time, you want to store your datetime in your database as UTC, which means - most of the time - you want to write your queries the same way (i.e., using GetUtcDate).
As a test, rewrite you query using GetUtcDate in place of GetDate, and see if your results change.

SQL Last Three Months

I have wrote SQL to select user data for last three months, but I think at the moment it updates daily.
I want to change it so that as it is now October it will not count Octobers data but instead July's to September data and change to August to October when we move in to November
This is the SQL I got at the moment:
declare #Today datetime
declare #Category varchar(40)
set #Today = dbo.udf_DateOnly(GETDATE())
set #Category = 'Doctors active last three months updated'
declare #last3monthsnew datetime
set #last3monthsnew=dateadd(m,-3,dbo.udf_DateOnly(GETDATE()))
delete from LiveStatus_tbl where Category = #Category
select #Category, count(distinct U.userid)
from UserValidUKDoctor_vw U
WHERE LastLoggedIn >= #last3monthsnew
How would I edit this to do that?
WHERE LastLoggedIn >= DATEADD(month, DATEDIFF(month, 0, GETDATE())-3, 0)
AND LastLoggedIn < DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0)
The above statement will return any results in July till before the start of current month.
Referencing this answer to get the first day of the month:
How can I select the first day of a month in SQL?
You can detect the month limitations like so:
select DATEADD(month, DATEDIFF(month, 0, getdate()) - 3, 0) AS StartOfMonth
select DATEADD(month, DATEDIFF(month, 0, getdate()), 0) AS EndMonth
Then you can add that into variables or directly into your WHERE clause:
declare #StartDate datetime
declare #EndDate datetime
set #StartDate = DATEADD(month, DATEDIFF(month, 0, getdate()) - 3, 0)
set #EndDate = DATEADD(month, DATEDIFF(month, 0, getdate()), 0)
select #Category, count(distinct U.userid)
from UserValidUKDoctor_vw U
where LastLoggedIn >= #StartDate AND LastLoggedIn < #EndDate
Or:
select #Category, count(distinct U.userid)
from UserValidUKDoctor_vw U
where LastLoggedIn >= DATEADD(month, DATEDIFF(month, 0, getdate()) - 3, 0)
and LastLoggedIn < DATEADD(month, DATEDIFF(month, 0, getdate()), 0)
How about using BETWEEN ?
WHERE LastLoggedIn
BETWEEN
DATEADD(month, DATEDIFF(month, 0, GETDATE())-3, 0)
AND
DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0)

SQL GROUP BY or JOIN

I am using SQL 2008 and just cannot get this query to work. I have a table with flight price details in it. There are many rows for each day for each route and I want to return the lowest price per day for the route and also the DateAdded (the datetime that the row was added). I am almost there as I seem to have managed to get the lowest price per day returned but I can't seem to get the correct dateadded to be returned. The code below seems to work to return the lowest price per day but I think I need some sort of join to also return the DateAdded?
ALTER PROCEDURE [dbo].[FlightInfoLowestPricePerDay]
(
#AirportFrom varchar(5),
#AirportTo varchar(5)
)
AS
select DATEADD(dd, 0, DATEDIFF(dd, 0, TimeDeparture)) as FlightDate, MIN(Price) as MinPrice
from FlightInfo
where AirportFrom = #AirportFrom and AirportTo = #AirportTo
AND TimeDeparture > DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()))
Group By DATEADD(dd, 0, DATEDIFF(dd, 0, TimeDeparture))
Order by FlightDate ASC
I have tried things such as the code below but I do not fully understand joins yet so have been struggling for quite a while although I'm sure I'm missing something very simple!
ALTER PROCEDURE [dbo].[FlightInfoLowestPricePerDay]
(
#AirportFrom varchar(5),
#AirportTo varchar(5)
)
AS
select DATEADD(dd, 0, DATEDIFF(dd, 0, fi1.TimeDeparture)) as FlightDate, MIN(fi1.Price) as MinPrice, fi2.DateAdded
from FlightInfo
fi1 join FlightInfo fi2 on fi1.Price = fi2.Price
where fi1.AirportFrom = #AirportFrom and fi1.AirportTo = #AirportTo
AND fi1.TimeDeparture > DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()))
Group By DATEADD(dd, 0, DATEDIFF(dd, 0, fi1.TimeDeparture))
Order by FlightDate ASC
Add fi2.DateAdded in Group By
ALTER PROCEDURE [dbo].[FlightInfoLowestPricePerDay]
(
#AirportFrom varchar(5),
#AirportTo varchar(5)
)
AS
select DATEADD(dd, 0, DATEDIFF(dd, 0, fi1.TimeDeparture)) as FlightDate, MIN(fi1.Price) as MinPrice, Cast(Convert(varchar(20),fi2.DateAdded,101) as datetime) DateAdded
from FlightInfo
fi1 join FlightInfo fi2 on fi1.Price = fi2.Price
where fi1.AirportFrom = #AirportFrom and fi1.AirportTo = #AirportTo
AND fi1.TimeDeparture > DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()))
Group By DATEADD(dd, 0, DATEDIFF(dd, 0, fi1.TimeDeparture)),Cast(Convert(varchar(20),fi2.DateAdded,101) as datetime)
Order by FlightDate ASC
OK I decided to simplify it a bit as I've wasted too much time on this already so now I am passing a specific date into the query and running the query multiple times to get the results I need:
ALTER PROCEDURE [dbo].[FlightInfoLowestPriceDateAddedForSpecificDate]
(
#AirportFrom varchar(5),
#AirportTo varchar(5),
#Date datetime
)
AS
select top 1 *
from FlightInfo
where AirportFrom = #AirportFrom and AirportTo = #AirportTo
AND DATEADD(dd, 0, DATEDIFF(dd, 0, TimeDeparture)) = DATEADD(dd, 0, DATEDIFF(dd, 0, #Date))
Order by Price asc
You want to use window function for this. One way is with row_number():
select flightDate, price
from (select DATEADD(dd, 0, DATEDIFF(dd, 0, TimeDeparture)) as FlightDate, fi.*,
ROW_NUMBER() over (partition by airportFrom, airportTo, DATEADD(dd, 0, DATEDIFF(dd, 0, TimeDeparture)) order by price) as seqnum
from FlightInfo fi
where AirportFrom = #AirportFrom and AirportTo = #AirportTo and
TimeDeparture > DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()))
) fi
where seqnum = 1
If you are using more recent versions of SQL Server, then you can take advantage of the date data type:
select flightDate, price
from (select cast(TimeDeparture as date) as FlightDate, fi.*,
ROW_NUMBER() over (partition by airportFrom, airportTo, cast(TimeDeparture as date) order by price) as seqnum
from FlightInfo fi
where AirportFrom = #AirportFrom and AirportTo = #AirportTo and
TimeDeparture > cast(getdate() as date)
) fi
where seqnum = 1
You can two sub queries (one that gets the small prices per day and the second one the DateAdded)
SELECT f1.FlightDate, f1.MinPrice, f2.DateAdded From
(
SELECT
DATEADD(dd, 0, DATEDIFF(dd, 0, fi1.TimeDeparture)) as FlightDate,
MIN(fi1.Price) as MinPrice
FROM FlightInfo fi1
WHERE fi1.AirportFrom = #AirportFrom and fi1.AirportTo = #AirportTo
AND fi1.TimeDeparture > DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()))
Group By
DATEADD(dd, 0, DATEDIFF(dd, 0, fi1.TimeDeparture))
) f1
INNER JOIN
(
SELECT DISTINCT
DATEADD(dd, 0, DATEDIFF(dd, 0, fi2.DateAdded)) AS DateAdded,
Price FROM FlightInfo fi2
WHERE fi2.AirportFrom = #AirportFrom and fi2.AirportTo = #AirportTo
AND fi2.TimeDeparture > DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()))
) f2 ON f2.Price = f1.MinPrice