SQL Procedure use - sql

Parameters are displaying an error and I typed them as follows:
where createdon between #startdate and #enddate
and pt.[state] in #([state])
and pt.carrier in (#Carrier)
and pt.LineOfBusiness IN (#LOB)
All these are added for the where clause

First, you are attempting to write:
where createdon between #startdate and #enddate and
pt.[state] in (#state) and
pt.carrier in (#Carrier) and
pt.LineOfBusiness in (#LOB)
This does not do what you want. Presumably you intend something like this:
where createdon >= #startdate and createdon < #enddate + interval 1 day and
pt.[state] = #state and
pt.carrier = #Carrier and
pt.LineOfBusiness = #LOB
Two notes:
in with a variable is exactly equivalent to =. So use that.
between ignores time components. Presumably, createdon has a time component, so this captures what is most likely your intended logic.
If you want to use in, then you cannot use a simple variable. Depending on the database, there may be way to implement a solution.

Related

Why is the GETDATE() function not working in IF condition?

I have created 1 code which should run only once in a day around 4 pm everyday.
The below condition I am running but it's not returning the desired output.
DECLARE #to_date AS date
SET #to_date = GETDATE()
IF #to_date = GETDATE()
BEGIN
INSERT INTO Tem1
SELECT * FROM Temp2
END
GetDate() is not deterministic. This means it can (and most probably does) give you a different value in each call. Using equals with getdate() will almost always be wrong. Try less than #to_date instead.
Because of precedence rules - date is implicitly converted to datetime for comparison. You expect the opposite.

Converting Date/Time from String Error When Using Cast

I am getting a "Unable to Convert Date/Time from Character String" error message when I run my Access query, but I am not sure why. I have used this method before and have not had any trouble.
SET NOCOUNT ON
DECLARE #StartDate date = '[Start date]', #EndDate date = '[End date]'
SELECT
CAST (Date as Date) as LocalDay
,SalesID
,Status
,Wait
,PO_Number
FROM
cpo_test.dbo.table_agent_detail_view
WHERE Date BETWEEN #StartDate And #EndDate
AND SOURCEID=1
Why is Cast not working in this instance?
The problem is not with the CAST, it's with
DECLARE #StartDate date = '[Start date]', #EndDate date = '[End date]'
I get the same error in SSMS if I try to execute that statement alone. The problem goes away if I change it to
DECLARE #StartDate date = '2018-01-01', #EndDate date = '2018-12-31'
It's not clear what you are trying to accomplish by assigning the string value '[Start date]' to a date variable, but you're going to have to figure out another way to do it.
Note: You call it your "Access query" but it is not Access SQL, it's T-SQL (SQL Server) so I assume that you're running it as a pass-through query in Access. If so, then be aware that pass-through queries behave quite differently from regular Access queries because they are not processed by the Access expression evaluator or the Access Database Engine, they are passed directly to the ODBC data source (hence the name "pass-through query").
I think you are missing a cast in Date near where condition on your query.
Try
SELECT
CAST (Date as Date) as LocalDay
,SalesID
,Status
,Wait
,PO_Number
FROM
cpo_test.dbo.table_agent_detail_view
WHERE CAST (Date as Date) BETWEEN #StartDate And #EndDate
AND SOURCEID=1

Using a Parameterized column in a Where Clause using Case

I am building a report in SSRS where I need to be able to let our users filter on different date fields. They need to be able to select the date filter and then the start and end dates within that filter.
This is a simplified Example of what I am trying to achieve:
SELECT Project.ProjectID, Project.Name, Project.Update_Date, Project.Due_Date, Project.Start_Date, Project.Review_Date
FROM Project
WHERE #datetypefiler BETWEEN #startdate AND #enddate
Where the #datetypefiler will essentially equal the field the user wishes to filter on (i.e. Project.Update_Date or Project.Due_Date etc)
On SSRS i built parameters for #datetypefiler which could equal the various date fields and I set up the start date and end date filter as expected.
Unfortunately it does not seem as though I can parameterize the #datetypefiler in this way? I then attempted to use the Case keyword as so:
SELECT Project.ProjectID, Project.Name, Project.Update_Date, Project.Due_Date, Project.Start_Date, Project.Review_Date
FROM Project
WHERE CASE
when #datetypefiler='Project.Update_Date' then Project.Update_Date BETWEEN #startdate AND #enddate
when #datetypefiler='Project.Due_Date' then Project.Due_Date BETWEEN #startdate AND #enddate
This isnt working for me either, I figure that instead of taking shots in the dark I should ask what the correct method would look like. Any advice on this would be greatly appreciated,
You could try something like this:
SELECT *
FROM Project
WHERE (#datetypefiler='Project.Update_Date'
AND Project.Update_Date BETWEEN #startdate AND #enddate)
OR (#datetypefiler='Project.Due_Date'
AND Project.Due_Date BETWEEN #startdate AND #enddate)
The OR will only evaluate the full statement if the #datetypefiler is matched.
Or you could try this
SELECT Project.ProjectID, Project.Name, Project.Update_Date, Project.Due_Date,
Project.Start_Date, Project.Review_Date
FROM Project
where
(CASE
when #datetypefiler = 'Project.Update_Date' then Project.Update_Date
when #datetypefiler= 'Project.Due_Date' then Project.Due_Date
END) BETWEEN #startdate AND #enddate
While both of other two answers are going to work just fine, they won't make use of index. I'd recommend to have two separate SELECT statements with two different queries based on your criteria, this way you can index your table both on Update_Date and Due_Date and actually use them to speed your queries up.

SQL query Performance when using Datetime in where / On clause

I have the 5l record in table. need to query...Which is one is query fast,Input parameter #RegistrationFrom DATE,#RegistrationTo DATE
Approach #1:
WHERE
CAST(Act.RegistrationOn AS DATE) BETWEEN CAST(#RegistrationFrom AS DATE)
AND CAST(#RegistrationTo AS DATE)
Approach #2 - convert into datetime:
DECLARE #From DATETIME, #Todate DATETIME;
SELECT #From = #RegistrationFrom;
SELECT #Todate = DATEADD(day, 1, #RegistrationTo);
WHERE
Act.RegistrationOn BETWEEN #From AND #Todate
Approach #3:
WHERE CONVERT(VARCHAR, Act.RegistrationOn,101) BETWEEN #From AND #Todate
I ma getting fast response approach 3 than above 1,2.
How it is working?
I would write the query as:
SELECT #Todate = DATEADD(day, 1, #RegistrationTo);
. . .
WHERE Act.RegistrationOn >= #From AND
Act.RegistrationOn < #Todate
Whether you use variables or a cast on the variable should have no or little affect on performance. More important considerations are the use of indexes and interpretability (does the code do what you intend).
Aaron Bertrand has a very good blog on why you shouldn't use BETWEEN for dates.
As for the first version . . . it is actually more reasonable than you might think. In general, function calls prevent the use of indexes on columns. However, SQL Server makes an exception for conversion of a datetime to date. So, it will still use an index.
That said, I would still go with the above version.
Try it like this:
WITH MyPrms AS
(
SELECT CAST(#RegistrationFrom AS DATE) AS fromD
,CAST(#RegistrationTo AS DATE) + 1 AS toD
)
SELECT *
FROM MyPrms
CROSS JOIN Act
WHERE Act.Registration>=fromD AND Act.RegistrationOn<toD;
It is fully inlineable (in VIEWS, functions...) and sargable (optimizer can use indexes)
EDIT just for clearity
By adding +1 to your upper border date (which was casted to a timeless DATE before, the upper border is midnight after the last day. By using a < you will get all data from the full day. BETWEEN includes the border which can lead to unexpected errors...
Both options are equivalent from performance point of view:
Approach 1
WHERE Act.RegistrationOn AS DATE BETWEEN CAST(#RegistrationFrom AS DATE) AND CAST(#RegistrationTo AS DATE)
Approach 2
WHERE RegistrationOn BETWEEN #From AND #Todate
Each casting in Approach 1 is executed only once and not for each row as you might expected.
For clarity, I would take option 2 or even better send the parameter with the right type to this query.
Also, an index on RegistrationOn column would definitively help. Please note a CAST on RegistrationOn column has been removed from Approach 1 as this would prevent SQL Server to use this index.
WHERE CONVERT(VARCHAR, Act.RegistrationOn,101) BETWEEN #From AND #Todate

Is it possible to set 2 variables with one set in T-SQL

Good morning Stack overflow.
At the top of one of my stored procedures I have 2 variables for my dates I use.
#StartDate is for the start of the current day and #EndDate is for the current time of the day.
DECLARE #StartDate DATE
DECLARE #EndDate DATETIME
SET #StartDate = GETDATE()
SET #EndDate = GETDATE()
PRINT #StartDate
PRINT #EndDate
I was wondering if it is possible to set both #StartDate and #EndDate to GETDATE() in the same line?
Thank you
I'll put you out of your misery: No, you can't. My guess here is that either you want both variables to be exactly the same (eliminating any possibility of two calls to GETDATE() returning different values, however small), or you just want fewer function calls. SQL Server doesn't support syntax like
SET #StartDate = #EndDate = GETDATE()
That's even leaving aside the implicit narrowing from DATETIME to DATE (althoguh that's not really an issue). Best you can do is
SET #StartDate = GETDATE()
SET #EndDate = #StartDate
Unless you just want to save a line in which case you can comma separate the #Variable = GETDATE() calls and only use one SELECT.
EDIT
Forgot to add this example - could reduce to one line thus:
SELECT #EndDate = GETDATE(), #StartDate = #EndDate
SET can only assign one variable at a time, but SELECT multiple.
so that's what you want:
SELECT #StartDate = GETDATE(), #EndDate = GETDATE()