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?
Related
Need help in getting the first date when getdate falls in between two dates.
Tried with the below code, but syntax is incorrect. I would like to get the output as 2018-09-29 from the below code:
DECLARE #Fromdt datetime
set #fromdt= (select case
when getdate()>='2018-09-01' and getdate()<='2018-09-13' then '2018-09-01'
when getdate()>='2018-09-15' and getdate()<='2018-09-27' then '2018-09-27'
when getdate()>='2018-09-29' and getdate()<='2018-10-10' then '2018-09-29'
when getdate()>='2018-10-12' and getdate()<='2018-10-24' then '2018-10-12'
end as frmdt from table1)
select #frmdt
In your query variable name in declaration and selection is not same and i just remove from table1 it works fine
DECLARE #Fromdt datetime
set #fromdt= (select case
when getdate()>='2018-09-01' and getdate()<='2018-09-13' then '2018-09-01'
when getdate()>='2018-09-15' and getdate()<='2018-09-27' then '2018-09-27'
when getdate()>='2018-09-29' and getdate()<='2018-10-10' then '2018-09-29'
when getdate()>='2018-10-12' and getdate()<='2018-10-24' then '2018-10-12'
end as frmdt)
select #Fromdt
Below link is fiddle link where i just check your query
https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=fbdf363ef76e176c4cf34f63cf07cfab
This is probably the query that you want
select #fromdt = case
when getdate()>='2018-09-01' and getdate()<='2018-09-13' then '2018-09-01'
when getdate()>='2018-09-15' and getdate()<='2018-09-27' then '2018-09-27'
when getdate()>='2018-09-29' and getdate()<='2018-10-10' then '2018-09-29'
when getdate()>='2018-10-12' and getdate()<='2018-10-24' then '2018-10-12'
end
note that getdate() returns date & time. If you only interested in the date alone, you can use convert(date, getdate()) to convert to date only
You can declare a current_date variable and use that in your query
declare #current_date date
select #current_date = getdate();
Write a single query to search between two dates and when To date is not available then it should search greater then first date.
For example: search between two dates, when both from and to dates are available
11-10-2015 to 11-10-2017
My query should also return result when To date is not available
For example: I want to write single query without any if and else
This code works and it is a single statement, as requested.
SELECT * from MyTable WHERE recordingdate BETWEEN COALESCE(#startdate,CAST('01/01/1753 00:00:00.000' AS DATETIME)) AND COALESCE(#enddate,CAST('12/31/9999 23:59:59.997' AS DATETIME))
If the start date is NULL, COALESCE will return the minimum date value, as defined by SQL Server. Otherwise, it returns the start date value sent in.
If the end date is NULL, COALESCE will return the maximum date value, as defined by SQL Server. Otherwise, it returns the end date sent in.
Feel free to turn the COALESCE statements for MIN and MAX possible dates into functions, as SQL Server does not have built-in functions for minimum and maximum possible dates.
Writing your code this way allows you to always execute a BETWEEN.
Try Thie below Logic
DECLARE #FromDt DATE='01/01/2017',#ToDate DATE = NULL
SELECT
*
FROM YourTable
WHERE FromDate > #FromDate
AND
(
#ToDate IS NULL
OR
(
#ToDate IS NOT NULL
AND
ToDate > #ToDate
)
)
declare #dt_from date = '20151011',
#dt_to date = '20171011' -- null
select *
from dbo.your_table
where date_field >= #dt_from and data <= isnull(#dt_to, '99990101');
I want to get date from yyyy-mm-dd to yyyy-mm-dd in SQL.
Example: I have two parameter #startdate : 2015-12-28 and #enddate : 2016-01-02, and database in SQLServer, datatype is varchar(10)
DATE_ORDER
28-12-2015
30-12-1996
29-12-2016
30-12-1997
24-12-2015
27-12-1993
03-01-2016
01-01-1992
02-01-2016
etc...
Ok,now I want to get data from #startdate : 2015-12-28 and #enddate : 2016-01-02. I use SELECT * FROM TABLE_X WHERE DATE_ORDER >= #startdate AND DATE_ORDER <= #enddate . But the results are not what I expected. Here are the results I want
28-12-2015
30-12-1996
29-12-2016
30-12-1997
01-01-1992
02-01-2016
I think to solve this problem, I need to do two things :
First, get date range from #startdate to #enddate , in here 28/12/2015, 29/12/2015, 30/12/2015, 31/12/2015, 01/01/2016, 02/01/2016.
The second: get the date in database same in range 28/12, 29/12, 30/12, 31/12, 01/01, 02/01, ignoring the year.
Can you give me some ideas about this ?
Your actual format is "105-italian" find details here.
You can convert your existing VARCHAR(10)-values with this line to real datetime
SELECT CONVERT(DATETIME,YourColumn,105)
Next thing to know is, that you should not use BETWEEN but rather >=StartDate AND < NakedDateOfTheFollowingDay to check date ranges
So to solve your need Get date-range from 2015-12-28 to 2016-01-02 you might do something like this:
DECLARE #Start DATETIME={d'2015-12-28'};
DECLARE #End DATETIME={d'2016-01-02'};
SELECT *
FROM YourTable
WHERE CONVERT(DATETIME,YourDateColumn,105)>=#Start AND CONVERT(DATETIME,YourDateColumn,105)<#End+1
Attention Be aware, that the conversion lets your expression be not sargable. No index will be used.
Better was to store your date as correctly typed data to avoid conversions...
Try this query
SET DATEFIRST 1
DECLARE #wk int SET #wk = 2
DECLARE #yr int SET #yr = 2011
--define start and end limits
DECLARE #todate datetime, #fromdate datetime
SELECT #fromdate = dateadd (week, #wk, dateadd (YEAR, #yr-1900, 0)) - 4 -
datepart(dw, dateadd (week, #wk, dateadd (YEAR, #yr-1900, 0)) - 4) + 1
SELECT #todate = #fromdate + 6
;WITH DateSequence( Date ) AS
(
SELECT #fromdate AS Date
UNION ALL
SELECT dateadd(DAY, 1, Date)
FROM DateSequence
WHERE Date < #todate
)
--select result
SELECT * FROM DateSequence OPTION (MaxRecursion 1000)
So, after the 2nd or 3rd edit, it slowly becomes clear, what you want (i hope).
So you REALLY WANT to get the dates with the year beeing ignored.
As someone pointed out already, date-values are stored internally not as string, but as internal datatype date (whatever that is in memory, i don't know).
If you want to compare DATES, you cannot do that with ignorance of any part. If you want to, you have to build a NEW date value of day and month of given row and a hard coded year (2000 or 1 or whatever) for EVERY row.
SELECT * FROM TABLE_X WHERE convert(date,'2000' + substring(convert(char(8),convert(datetime, 'DATE_ORDER', 105),112),5,4),112) >= #startdate AND convert(date,'2000' + substring(convert(char(8),convert(datetime, 'DATE_ORDER', 105),112),5,4),112) <= #enddate
If your startdate and enddate go OVER sylvester, you have to do 2 queries, on from startdate to 1231, one from 0101 to enddate.
My stored proc has the following select statement:
select Name,Holiday from tblNames where ID = #ID and DATENAME(YEAR, GETDATE()) = #Year
When executing the statement I have an error
"Error converting data type int to nvarchar."
How can I convert #Year parameter to a correct year?
The return type of the datename function is nvarchar, you want the datepart function that returns an integer value, so change to DATEPART(YEAR, GETDATE()) instead.
datename is what you would use to get the name of a month or weekday.
Or you could use the year(getdate()) function instead as Gordon L mentioned in a comment.
I'd recommend to switch back from fixing specific error message to the original question. You have a date in your table and need to filter it by range. So just provide to server the range bounds. This will also avoid any conversions of stored data. To avoid tail time issue you may append '23:59:59.997' to the upper bound of range or (my advice) provide next date and compare by < instead of <=
set #startdate = ...
set #enddate = dateadd(dd, 1, ...)
select *
from mytable
where t.date >= #startdate and t.date < #enddate
Complicated conversions can make it impossible to use appropriate index. If you can convert your arguments and provide prepared values to server - strive to do so.
I am running a SQL Statement, shown below. This is ultimately going to be used to populate a reporting table nightly with the days transactions. When I run it without the
Cast(M._CreateDateTime as Date) = #StartDate
It takes 1:40.
With the function back in the where clause it takes over 10 minutes.
Declare #StartDate DAte = GetDate()
If Object_ID ('tempdb.dbo.#WinBack') is not null Drop Table #WinBack
Select
M.HospitalMasterID
,M.TxnSite
,P.ClientID
,M.PatientID
,M.TxnDate as CallDate
,M.TxnCode
,M.EnteredMasterID
,U.UserName
,U.UserDept
Into
#WinBack
From
Avimark_OLTP.dbo.MedicalHistory as M
Inner JoinAvimark_OLTP.dbo.Patient as P on
M.HospitalMasterID = P.HospitalMasterID and
M.PatientID = P.PatientID
Left Outer Join RptSys.dbo.Ref_User as U on
M.EnteredMasterID = U.UserMastID
Where
Cast(M._CreateDateTime as Date) = #StartDate and
M.TxnCode = 'RemCall' and
U.UserName is not null
Does anyone have any suggestions on how to speed this up? I know it is the cast part that is killing it.
Thanks,
Using function for a column makes SQL Server both cast every single row in the table it's comparing and preventing index usage, you should do it like this:
Declare #StartDate Date, #EndDate Date
set #StartDate = GetDate()
set #EndDate = dateadd(day, 1, #StartDate)
select
...
where
M._CreateDateTime >= #StartDate and
M._CreateDateTime < #endDate