I need to find the last occurence of a date (in my case a static date 1st of may)
I made this which works but i know this can be done in a much smarter way
declare #lastmay date
set #lastmay = DATEADD(YY,YEAR(GETDATE())-2000,'20000501')
IF #lastmay <= GETDATE()
BEGIN
SET #lastmay = DATEADD(YY,-1,#lastmay)
END
When you are working with dates in SQL it can be a real help to have a Dates utility table on your database that you can then compare against.
This article discusses it well: http://www.techrepublic.com/blog/datacenter/simplify-sql-server-2005-queries-with-a-dates-table/326
If you implemented that your queries could become quite simple such as (using columns from article)
Declare #lastmay date
Select #lastmay = DateFull
from DateLookup
where MonthNumber = 5
and MonthDay = 1
and Datefull < getdate()
Related
I have wrote a script (from the internet) but it's not working because of some logical error I guess.
ALTER FUNCTION EstDateCheck (#CoustDesireddate varchar(10))
RETURNS varchar(20)
AS
BEGIN
declare #testDate Date = (SELECT STUFF(#CoustDesireddate, 4, 0, '01/'));
declare #lastWorkDay date = iif(DATEPART(WEEKDAY, EOMONTH(#testDate)) <= 5
,EOMONTH(#testDate)
,DATEADD(DAY, -(7-DATEPART(WEEKDAY, EOMONTH(#testDate))),EOMONTH(#testDate)))
RETURN #lastWorkDay
END
This is how I execute
select dbo.EstDateCheck('07/2022')
I would, honestly, consider creating a calendar table. There are plenty of examples out there, so I'm not going to cover how to create one; plus what columns you need vary.
What you will have, however, is a column to denote if the day is a weekday (and probably a working day), as well as what month and year it belongs to. As a result you can then simply get the last weekday with the following query:
SELECT MAX(CalendarDate)
FROM dbo.CalendarTable
WHERE CalendarYear = 2022
AND CalendarMonth = 7
AND Weekday = 1;
If you therefore wanted to do this as a function, you could use an inline table value function:
CREATE FUNCTION dbo.MonthLastWeekday (#Year int, #Month int)
RETURNS table
AS RETURN
SELECT MAX(CalendarDate) AS LastWeekday
FROM dbo.CalendarTable
WHERE CalendarYear = #Year
AND CalendarMonth = #Month
AND Weekday = 1;
And then you would call the function as follows:
SELECT LastWeekday
FROM dbo.MonthLastWeekday(#Year,#Month);
any idea why when i use this code
SELECT * FROM Runtime.dbo.AnalogHistory WHERE TagName = 'LT73011.Out_PV'
AND datediff(HOUR, DateTime, '2018-03-14 08:02:23.449') = 0
knowing that Runtime.dbo.AnalogHistory is my view
i get blank
but when i query with this
SELECT * FROM Runtime.dbo.AnalogHistory WHERE TagName = 'LT73011.Out_PV'
AND DateTime <= '2018-03-14 08:59:00.000'
i get all the values that happened at the hour 8am
is there's a curtain restriction with a view? how can i work around this?
I can't reproduce your observations/behavior, but if you want an exact way to target 8am on a certain date then try this:
SELECT *
FROM Runtime.dbo.AnalogHistory
WHERE
TagName = 'LT73011.Out_PV' AND
DateTime >= '2018-03-14 08:00:00' AND DateTime < '2018-03-14 09:00:00';
This approach also has the added advantage that an index on the DateTime column can be used (i.e. the WHERE clause is sargable).
ALTER PROCEDURE [dbo].[spInsert]
(#PlanName Varchar(50)=null
,#StartDate Datetime
,#EndDate Datetime
,#ModifiedBy Varchar(100)=null
,#ReturnValue Int Out)
As
BEGIN
IF NOT EXISTS(SELECT PlanName FROM dbo.tblPlan WHERE PlanName=#PlanName)
BEGIN
IF((SELECT COUNT(*) FROM tblPlan WHERE StartDate <= #StartDate AND EndDate <=
#EndDate)<0)
BEGIN
INSERT INTO dbo.tblPlan VALUES(3,#PlanName,#StartDate,#EndDate,#ModifiedBy,GETDATE(),
(SELECT DATEDIFF(DD,#StartDate,#EndDate)))
SET #ReturnValue=1;
END
ELSE
SET #ReturnValue=-2;
END
ELSE
SET #ReturnValue=-1;
END
I am trying to achieve the below thing.I want to check user supplied startDate and Enddate is in between the existing table startdate and enddate. if any of the date of user supplied date range is in between the tables start date and end date,it should return -2,if the record does not exists it should insert the details..
I Could not achieve this logic.where i went wrong ..please suggest me any solution to this.
EDIT:First Consditon check whether planName is exists or not,If not exists then want to check Start and End Date already existed or Not(Including start and End)
I tried two ways as suggested mentioned in the replies.
eg:If existing start and end range is Start-2013-10-09,End-2013-10-15,If am going to insert another plan then the start and end date of this plan should not fall between 9th-15th october and start and End date should not be 9th or 15 th both.
ONE:IF((SELECT COUNT(*) FROM tblPlan WHERE StartDate <= #StartDate AND EndDate <=
#EndDate)=0)
Result: It does not insert any data, even it is out of previous date. or with in the
range
SECOND:IF((SELECT COUNT(*) FROM tblPlan WHERE StartDate>=#StartDate AND
EndDate<=#EndDate)=0)
RESULT: It insert the date with out Considering the above condition.
I think you need to change your if from
IF((SELECT COUNT(*) FROM tblPlan WHERE StartDate <= #StartDate AND EndDate <= #EndDate)<0)
to
IF((SELECT COUNT(*) FROM tblPlan WHERE StartDate <= #StartDate AND EndDate >= #EndDate)=0)
Which should ensure that #StartDate and #EndDate is between StartDate and EndDate and test for =0
COUNT(*) can never be smaller than zero like your code suggests.
It's either a positive integer (which is greater than zero), or null, which will also return false on any arithmetic condition.
try the below :
ALTER PROCEDURE [dbo].[spInsert]
(#PlanName Varchar(50)=null
,#StartDate Datetime
,#EndDate Datetime
,#ModifiedBy Varchar(100)=null
,#ReturnValue Int Out)
As
BEGIN
IF NOT EXISTS(SELECT PlanName FROM dbo.tblPlan WHERE PlanName=#PlanName)
BEGIN
IF((SELECT COUNT(*) FROM tblPlan WHERE StartDate >= #StartDate AND EndDate <=
#EndDate)=0)
BEGIN INSERT INTO dbo.tblPlan
VALUES(3,#PlanName,#StartDate,#EndDate,#ModifiedBy,GETDATE(),
(SELECT DATEDIFF(DD,#StartDate,#EndDate)))
SET #ReturnValue=1;
END
ELSE
SET #ReturnValue=-2;
END
ELSE
SET #ReturnValue=-1;
END
As count always return positive value or zero. so your first condition always being false.
*UPDATE:*
you want to say if Sdate is '12-12-2013' and edate is '15-12-2013' then you don't want to considers these dates in check if so then try replace the query with below:
IF((SELECT COUNT(*) FROM tblPlan WHERE StartDate > #StartDate AND EndDate <
#EndDate)=0)
If you're wanting to check whether the period defined by #StartDate,#EndDate overlaps with any period defined by the values in the StartDate,EndDate columns for a particular row, then the actual comparison that you want to perform is:
StartDate < #EndDate AND EndDate < #StartDate
(With appropriate adjustments of < to <= depending on whether you want to consider two periods such that one starts at the exact time that the other finishes as overlapping or not)
The logic is - Two periods overlap if both of the following conditions are true:
period 1 starts before period 2 ends
period 2 starts before period 1 ends
Other notes -
A COUNT will never be <0 so that part of the logic is incorrect. If you merely want to determine whether any rows exists, use EXISTS (as you already have once) - don't force a COUNT if you don't actually need to know how many rows match your criteria.
I also find it slightly suspect that your first query considers PlanName but your second doesn't. Are you sure that this is correct?
Is it possible to have indexes on DateTime parts such as DATEPART(YEAR, bp.[CreatedOn]) and DATEPART(MONTH, bp.[CreatedOn])? For example, I have the following T-SQL query:
DECLARE #year AS INT = 2012;
DECLARE #month AS INT = 8;
SELECT bp.Title, bp.CreatedOn FROM BlogPosts bp
WHERE (DATEPART(YEAR, bp.[CreatedOn]) = #year) AND (DATEPART(MONTH, bp.[CreatedOn]) = #month)
ORDER BY bp.CreatedOn;
And this is the execution plan I have: https://gist.github.com/3551450
Currently, there are not many records so it is not a big problem in terms of perf but the records will grow over the time.
You'd better construct criterion using datetime field:
declare #startMonth datetime = '20120801'
SELECT bp.Title, bp.CreatedOn
FROM BlogPosts bp
WHERE bp.[CreatedOn] >= #startMonth
AND bp.[CreatedOn] < dateadd (month, 1, #startMonth)
ORDER BY bp.CreatedOn;
This way query executor will be able to use index on CreatedOn.
Yes is it possible to put index on year and month. Here is an example:
create table testt(d datetime)
alter table testt add year as year(d) PERSISTED -- after marc_s advise. Thx
alter table testt add month as month(d) PERSISTED --
create index idx_year on testt(year)
create index idx_month on testt(month)
However I would always use a variation of Nikola's solution, so +1 to Nikola.
This is how you can rewrite month and year into a date:
DECLARE #year AS INT = 2012;
DECLARE #month AS INT = 8;
DECLARE #from DATE = dateadd(month, (#year-1900)*12 + #month - 1, 0)
I suggest you store date parts on different fields. Clearly this is a requirement which exist in your domain as such needs to be part of your model.
What you lose is that you have to construct the datetime for every model you load or you set the value but that would be a few CPU cycles.
I give two different date as a input. i want to find, what are date between two date..
For eg:
1'st Input is : 2011-02-20
2'nd input is : 2011-02-25
Output is:
2011-02-20
2011-02-21
2011-02-22
2011-02-23
2011-02-24
2011-02-25
Is there any function to find the between date...
otherwise how to find ?
You can use a CTE to achieve this.
DECLARE #StartDate DATETIME
DECLARE #EndDate DATETIME
SET #StartDate = '2011-02-20'
SET #EndDate = '2011-02-25'
;WITH GetDates AS
(
SELECT 1 as counter, #StartDate AS Date
UNION ALL
SELECT counter + 1, DATEADD( day, counter, #StartDate )
FROM GetDates
WHERE DATEADD( day, counter, #StartDate ) <= #EndDate
)
SELECT Date FROM GetDates
See:
Why should I consider using an auxiliary calendar table?
A calendar table can make it much
easier to develop solutions around any
business model which involves dates.
Last I checked, this encompasses
pretty much any business model you can
think of, to some degree. Constant
problems that end up requiring
verbose, complicated and inefficient
methods include the following
questions: How many business days
between x and y? ...
SELECT Date = #StartDate + number
FROM master..spt_values
WHERE type = 'P'
AND number BETWEEN 0 AND DATEDIFF(day, #StartDate, #EndDate)
Note: This solution is not applicable when the distance between the two dates is more than 2047 days.