Variables make query performance worse - sql

I have this query and the performance slows down drastically when I declare variables:
DECLARE #StartDate DATETIME,
#EndDate DATETIME
SET #StartDate = '2018-08-13'
SET #EndDate = '2018-08-19'
SELECT *
FROM [DIME_WH].[dbo].[FactOrderLines2] FL (nolock)
WHERE DD_OrderDate >= #StartDate
AND DD_OrderDate <= #EndDate
This is much slower than this SQL statement:
SELECT *
FROM [DIME_WH].[dbo].[FactOrderLines2] FL (nolock)
WHERE DD_OrderDate >= '2018-08-01'
AND DD_OrderDate <= '2018-08-17'
Both queries will return the same results in the end.

SELECT * FROM [DIME_WH].[dbo].[FactOrderLines2] FL (nolock)
WHERE DD_OrderDate >= '2018-08-01'
AND DD_OrderDate <= '2018-08-17'
When constant is used in parameter, then Optimiser create special plan for this query.so if same query is executed with same value then plan is reuse, if value is change then another plan is created.
So Parameter with constant value is fast.
SELECT *
FROM [DIME_WH].[dbo].[FactOrderLines2] FL (nolock)
WHERE DD_OrderDate >= #StartDate
AND DD_OrderDate <= #EndDate
When variable is use in parameter.Then Optimizer create Execution plan for the First parameter value that was passed .
For Example #StartDate='2018-08-01' and #EndDate='2018-08-07' value were pass for first time.
Then optimal execution plan is created by optimiser. This plan is good enough for this value.
Next Time #StartDate='2018-08-01' and #EndDate='2018-08-31' value is pass then same previous plan is use which may not be optimal for this parameter.
In another word same plan which was Optimal for first value is Sub optimal for another value.
so query may perform poor and slow.This is known as Parameter sniffing.
There are several ways to overcome this problem.
Parameter Sniffing
Note : In this thread we are only focussing on why variable performance is slow while other factor remaining constant.

This is because SQL Server does not know the values of your variables at optimization time - when it makes an estimate and can not look up any statistics for it (as a one possibility), so it's (most likely) just scans the whole table instead of make a lookup (seek). They can be "sniffed" if used inside of stored procedure or parameterized with sp_executesql

The problem could be parameter sniffing, maybe not. I'll skip that topic since #KumarHarsh already covered it. The most important question here is: What data type is FactOrderLines.DD_OrderDate? This is important for performance reasons as well as correctness.
First for performance. If DD_OrderDate is a DATE datatype and your variables or parameters are DATETIME then the optimizer has to jump through extra hoops to utilize your index or will be forced to do a scan instead of a seek. Note the following sample data:
USE tempdb;
GO
IF OBJECT_ID('#FactOrderLines') IS NOT NULL DROP TABLE #FactOrderLines;
GO
CREATE TABLE #FactOrderLines(someId INT IDENTITY, DD_OrderDate DATETIME NOT NULL);
CREATE CLUSTERED INDEX nc_factOrderLines ON #FactOrderLines(DD_OrderDate);
INSERT #FactOrderLines(DD_OrderDate)
SELECT TOP (10000) DATEADD(DAY,CHECKSUM(NEWID())%100, getdate())
FROM sys.all_columns;
GO
Now let's compare the execution plans for the following queries:
-- AS DATE
DECLARE #StartDate DATE = '2018-08-01',
#EndDate DATE = '2018-08-20';
SELECT *
FROM #FactOrderLines
WHERE DD_OrderDate >= #StartDate
AND DD_OrderDate <= #EndDate
OPTION (RECOMPILE)
GO
-- AS DATETIME
DECLARE #StartDate DATETIME = '2018-08-01',
#EndDate DATETIME = '2018-08-31';
SELECT *
FROM #FactOrderLines
WHERE DD_OrderDate >= #StartDate
AND DD_OrderDate <= #EndDate
OPTION (RECOMPILE);
Execution plans:
For this reason - you want to make sure that you're using the same datatype for your variables/parameters as for the column they are working against.
Now about correctness; note this query:
DECLARE #StartDate DATE = '2018-08-01',
#EndDate DATE = '2018-08-20';
SELECT
[getdate as datetime] = GETDATE(),
[#enddate as datetime] = CAST(#EndDate AS DATETIME),
[getdate as date] = CAST(GETDATE() AS DATE),
[datetime equality] = IIF(GETDATE() > #EndDate,'yep','nope'),
[date equality] = IIF(CAST(GETDATE() AS DATE) > #EndDate,'yep','nope');
Results:
getdate as datetime #enddate as datetime getdate as date datetime equality date equality
----------------------- ----------------------- --------------- ----------------- -------------
2018-08-20 13:52:46.247 2018-08-20 00:00:00.000 2018-08-20 yep nope
Values of the date format translate into datetime as 0 hour, 0 second...

Related

SQL Server 2014. Fastest way to update a numeric field

I can think of this 2 options, but not sure if there is any other one. What will be faster?
DECLARE #dateVar datetime = '20170101';
UPDATE SALESLINE
SET REMAINSALESFINANCIAL= 0
WHERE CONVERT(DATE, CREATEDDATETIME) < CONVERT(DATE, #dateVar)
or
DECLARE #dateVar datetime = '20170101';
UPDATE SALESLINE
SET REMAINSALESFINANCIAL= 0
WHERE CONVERT(DATE, CREATEDDATETIME) < CONVERT(DATE, #dateVar)
AND REMAINSALESFINANCIAL != 0
REMAINSALESFINANCIAL is numeric
I have an index on CREATEDDATETIME
Assuming that REMAINSALESFINANCIAL does not contain any NULLs you can just use
UPDATE SALESLINE
SET REMAINSALESFINANCIAL = 0
WHERE CREATEDDATETIME < CONVERT(DATE, #dateVar)
AND REMAINSALESFINANCIAL <> 0
As CONVERT(DATE, #dateVar) will have a time part of 00:00:00 and so any datetime that is less than this must have a date part of the previous day or earlier.
Casting a datetime column to date doesn't prevent index use but it is more optimal not to.
I agree with the other answers that the second option should be faster but there are additional considerations from a performance perspective.
If the assigned value has a time of midnight, the explicit conversion is unnecessary.
Instead of a local variable, I suggest the query be parameterized so that stats histogram is used instead of average cardinality to better optimize the query. This is automatic if your actual query uses a stored procedure parameter directly or is called as a parameterized query from application code. If parameter sniffing is an issue (unlikely here, IMHO), add an OPTION RECOMPILE query hint.
EXEC sp_executesql N'
UPDATE SALESLINE
SET REMAINSALESFINANCIAL= 0
WHERE
CREATEDDATETIME < #dateVar
AND REMAINSALESFINANCIAL <> 0;'
, N'#dateVar datetime'
, #dateVar = '20180101';
The second version is better. If you have some rows where REMAINSALESFINANCIAL = 0, then the engine will not even try to update those rows, filtering them out earlier in the process. Note: this assumes that REMAINSALESFINANCIAL is never NULL.
In general, having a function on a column in the WHERE is a bad idea. In this case, though, SQL Server will still use an index, so that is not a problem.
It would be interesting to compare the performance with an index on (CREATEDDATETIME) versus (CREATEDDATETIME, REMAINSALESFINANCIAL). In the first case, it has to work harder to find the rows to update. In the second, it has to update the index when it changes the values.

SELECT WHERE Date = Day

I have a table with a column of type dateTime. I want to do a query that selects all rows that take place on that date. Basically,
SELECT * FROM Table
WHERE [timeStamp] = '02-15-2003'
But that only returns rows where [timeStamp] is '02-15-2003 00:00:00.000', but really I want rows from anytime that day.
If you have indexes, you are going to want something which doesn't prevent the indexes from being used:
SELECT *
FROM Table
WHERE [timeStamp] >= '20030215'
AND [timeStamp] < '20030216'
You can do a truncation operation on the [timeStamp] column to get rid of any time part (implementation dependent), but this can potentially hurt the execution plan. Unfortunately, you really have to look at the execution plan to see this, because sometimes the optimizer is clever about some functions and sometimes it isn't.
You should CAST to DATE if you're on SQL 2008.
select * from [Table]
where cast([timeStamp] as date) = '02-15-2003'
Best approach to remove time part of datetime in SQL Server
--- UPDATE ---
The word the commenters should have used back in 2012 to describe why this is not the optimal solution is sargability. Changing the data type in the WHERE clause, while the simplest solution, has implications for index usage that a bounded search would not.
 
in sql server 2008 + :
SELECT * FROM Table
        WHERE cast( [timeStamp] as date)  = '02-15-2003'
or
just ZERO the time part :  ( 2005+)
SELECT * FROM Table
WHERE DateAdd(day, DateDiff(day, 0, [timeStamp]), 0) = '02-15-2003'
MS SQL 2014, this works perfect:
SELECT [YourDateColumn] FROM [YourTable] WHERE(DATEPART(dd,[YourDateColumn]) = '29')
Might have some performance issues on very large DB's.
try this.. SQL SERVER
SELECT * FROM Table WHERE convert(date,[timestamp]) = '2003-02-15'
should return all rows on the specified day.
I would create a stored procedure that will accept "start date" and "end date"
In this case the start date and end date can be the same
This ensures that all rows from 12:01 AM to 11:59 PM are returned
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create PROCEDURE TestBetweenDates
-- Add the parameters for the stored procedure here
#StartDate DateTime = 0,
#EndDate DateTime = 0
AS
BEGIN
SET NOCOUNT ON;
SET #StartDate = cast(Convert(varchar(10), DateAdd(d, -6, #StartDate ), 101) + ' 12:01 AM' as datetime)
SET #EndDate = cast(Convert(varchar(10), DateAdd(d, -0, #EndDate), 101) + ' 11:59 PM' as datetime)
SELECT * FROM Table
WHERE ([timeStamp] BETWEEN #StartDate AND #EndDate)
END
GO
Date comparisons can be a tricky thing.
Remember that it is a datetime and not a string. This is why you got unexpected results.
For the specific query you have in mind, the appropriate query is
SELECT * FROM Table
WHERE 0 = datediff(day,[timestamp],'02-15-2003')
You may also do compares by month() and year() which return integer values.
You usually have to write custom functions to get comparisons that are non-trivial.
Also note
WHERE 0 = datediff(day,[timestamp],'02-15-2003')
is much better than
WHERE datediff(day,[timestamp],'02-15-2003') = 0
The former does not interfere with internal efficiency while the latter does.

How to make faster this statement : "paramDate Between startDate and NULL"?

This query is taking long time when endDate is null (i think that its about case statement, before case statement it was fast)
SELECT *
FROM HastaKurumlari
WHERE CONVERT(SMALLDATETIME,'21-05-2009',103)
BETWEEN startDate
AND (CASE WHEN endDate IS NULL THEN GETDATE() ELSE endDate END)
What should i use, when endDate is null to make it faster ?
Here's the query without CONVERT or CASE:
SELECT *
FROM HastaKurumlari
WHERE '21-05-2009' between startDate and IsNull(endDate,getdate())
To make sure Sql Server doens't evaluate getdate() for every row, you could cache it, although I'm pretty sure Sql Server is smart enough by default:
declare #now datetime
set #now = getdate()
SELECT *
FROM HastaKurumlari
WHERE '21-05-2009' between startDate and IsNull(endDate,#now)
Posting the query plan could help explain why the query is slow:
SET SHOWPLAN_TEXT ON
go
SELECT *
FROM HastaKurumlari
WHERE CONVERT(SMALLDATETIME,'21-05-2009',103)
BETWEEN startDate
AND (CASE WHEN endDate IS NULL THEN GETDATE() ELSE endDate END)
If it is performance critical, then perhaps just don't use null for the open end-date - use the maximum supported datetime instead (probably lots of 9s).
I'd also do the conversion separately:
DECLARE #when datetime
SET #when = CONVERT(SMALLDATETIME,'21-05-2009',103)
SELECT *
FROM HastaKurumlari
WHERE #when
BETWEEN startDate AND endDate
There is still something a bit different in the above and your original; if you can explain the intent of the GETDATE() check I might be able to tidy (read:fix) it a bit.
As a starting point, factor out GETDATE() so that its called just once, and you should see an improvement in speed.
The way you've written it you are asking for GETDATE() to be evaluated every time enddate is null.
Since GETDATE() is a non-deterministic function the query cannot be optimised and will tend to under perform.
You could try the coalesce function:
select *
from HastaKurumlari
where convert(smalldatetime, '21-05-2009', 103)
between startDate and coalesce(endDate, getdate());
The only way to be certain is to try any alternatives and view the execution plan generated for each query.

How can I compare time in SQL Server?

I'm trying to compare time in a datetime field in a SQL query, but I don't know if it's right. I don't want to compare the date part, just the time part.
I'm doing this:
SELECT timeEvent
FROM tbEvents
WHERE convert(datetime, startHour, 8) >= convert(datetime, #startHour, 8)
Is it correct?
I'm asking this because I need to know if 08:00:00 is less or greater than 07:30:00 and I don't want to compare the date, just the time part.
Thanks!
Your compare will work, but it will be slow because the dates are converted to a string for each row. To efficiently compare two time parts, try:
declare #first datetime
set #first = '2009-04-30 19:47:16.123'
declare #second datetime
set #second = '2009-04-10 19:47:16.123'
select (cast(#first as float) - floor(cast(#first as float))) -
(cast(#second as float) - floor(cast(#second as float)))
as Difference
Long explanation: a date in SQL server is stored as a floating point number. The digits before the decimal point represent the date. The digits after the decimal point represent the time.
So here's an example date:
declare #mydate datetime
set #mydate = '2009-04-30 19:47:16.123'
Let's convert it to a float:
declare #myfloat float
set #myfloat = cast(#mydate as float)
select #myfloat
-- Shows 39931,8244921682
Now take the part after the comma character, i.e. the time:
set #myfloat = #myfloat - floor(#myfloat)
select #myfloat
-- Shows 0,824492168212601
Convert it back to a datetime:
declare #mytime datetime
set #mytime = convert(datetime,#myfloat)
select #mytime
-- Shows 1900-01-01 19:47:16.123
The 1900-01-01 is just the "zero" date; you can display the time part with convert, specifying for example format 108, which is just the time:
select convert(varchar(32),#mytime,108)
-- Shows 19:47:16
Conversions between datetime and float are pretty fast, because they're basically stored in the same way.
convert(varchar(5), thedate, 108) between #leftTime and #rightTime
Explanation:
if you have varchar(5) you will obtain HH:mm
if you have varchar(8) you obtain HH:mm ss
108 obtains only the time from the SQL date
#leftTime and #rightTime are two variables to compare
If you're using SQL Server 2008, you can do this:
WHERE CONVERT(time(0), startHour) >= CONVERT(time(0), #startTime)
Here's a full test:
DECLARE #tbEvents TABLE (
timeEvent int IDENTITY,
startHour datetime
)
INSERT INTO #tbEvents (startHour) SELECT DATEADD(hh, 0, GETDATE())
INSERT INTO #tbEvents (startHour) SELECT DATEADD(hh, 1, GETDATE())
INSERT INTO #tbEvents (startHour) SELECT DATEADD(hh, 2, GETDATE())
INSERT INTO #tbEvents (startHour) SELECT DATEADD(hh, 3, GETDATE())
INSERT INTO #tbEvents (startHour) SELECT DATEADD(hh, 4, GETDATE())
INSERT INTO #tbEvents (startHour) SELECT DATEADD(hh, 5, GETDATE())
--SELECT * FROM #tbEvents
DECLARE #startTime datetime
SET #startTime = DATEADD(mi, 65, GETDATE())
SELECT
timeEvent,
CONVERT(time(0), startHour) AS 'startHour',
CONVERT(time(0), #startTime) AS '#startTime'
FROM #tbEvents
WHERE CONVERT(time(0), startHour) >= CONVERT(time(0), #startTime)
Just change convert datetime to time that should do the trick:
SELECT timeEvent
FROM tbEvents
WHERE convert(time, startHour) >= convert(time, #startHour)
if (cast('2012-06-20 23:49:14.363' as time) between
cast('2012-06-20 23:49:14.363' as time) and
cast('2012-06-20 23:49:14.363' as time))
One (possibly small) issue I have noted with the solutions so far is that they all seem to require a function call to process the comparison. This means that the query engine will need to do a full table scan to seek the rows you are after - and be unable to use an index. If the table is not going to get particularly large, this probably won't have any adverse affects (and you can happily ignore this answer).
If, on the other hand, the table could get quite large, the performance of the query could suffer.
I know you stated that you do not wish to compare the date part - but is there an actual date being stored in the datetime column, or are you using it to store only the time? If the latter, you can use a simple comparison operator, and this will reduce both CPU usage, and allow the query engine to use statistics and indexes (if present) to optimise the query.
If, however, the datetime column is being used to store both the date and time of the event, this obviously won't work. In this case if you can modify the app and the table structure, separate the date and time into two separate datetime columns, or create a indexed view that selects all the (relevant) columns of the source table, and a further column that contains the time element you wish to search for (use any of the previous answers to compute this) - and alter the app to query the view instead.
Using float does not work.
DECLARE #t1 datetime, #t2 datetime
SELECT #t1 = '19000101 23:55:00', #t2 = '20001102 23:55:00'
SELECT CAST(#t1 as float) - floor(CAST(#t1 as float)), CAST(#t2 as float) - floor(CAST(#t2 as float))
You'll see that the values are not the same (SQL Server 2005). I wanted to use this method to check for times around midnight (the full method has more detail) in which I was comparing the current time for being between 23:55:00 and 00:05:00.
Adding to the other answers:
you can create a function for trimming the date from a datetime
CREATE FUNCTION dbo.f_trimdate (#dat datetime) RETURNS DATETIME AS BEGIN
RETURN CONVERT(DATETIME, CONVERT(FLOAT, #dat) - CONVERT(INT, #dat))
END
So this:
DECLARE #dat DATETIME
SELECT #dat = '20080201 02:25:46.000'
SELECT dbo.f_trimdate(#dat)
Will return
1900-01-01 02:25:46.000
Use Datepart function: DATEPART(datepart, date)
E.g#
SELECT DatePart(#YourVar, hh)*60) +
DatePart(#YourVar, mi)*60)
This will give you total time of day in minutes allowing you to compare more easily.
You can use DateDiff if your dates are going to be the same, otherwise you'll need to strip out the date as above
You can create a two variables of datetime, and set only hour of date that your need to compare.
declare #date1 datetime;
declare #date2 datetime;
select #date1 = CONVERT(varchar(20),CONVERT(datetime, '2011-02-11 08:00:00'), 114)
select #date2 = CONVERT(varchar(20),GETDATE(), 114)
The date will be "1900-01-01" you can compare it
if #date1 <= #date2
print '#date1 less then #date2'
else
print '#date1 more then #date2'
SELECT timeEvent
FROM tbEvents
WHERE CONVERT(VARCHAR,startHour,108) >= '01:01:01'
This tells SQL Server to convert the current date/time into a varchar using style 108, which is "hh:mm:ss". You can also replace '01:01:01' which another convert if necessary.
I believe you want to use DATEPART('hour', datetime).
Reference is here:
http://msdn.microsoft.com/en-us/library/ms174420.aspx
I don't love relying on storage internals (that datetime is a float with whole number = day and fractional = time), but I do the same thing as the answer Jhonny D. Cano. This is the way all of the db devs I know do it. Definitely do not convert to string. If you must avoid processing as float/int, then the best option is to pull out hour/minute/second/milliseconds with DatePart()
I am assuming your startHour column and #startHour variable are both DATETIME; In that case, you should be converting to a string:
SELECT timeEvent
FROM tbEvents
WHERE convert(VARCHAR(8), startHour, 8) >= convert(VARCHAR(8), #startHour, 8)
below query gives you time of the date
select DateAdd(day,-DateDiff(day,0,YourDateTime),YourDateTime) As NewTime from Table
#ronmurp raises a valid concern - the cast/floor approach returns different values for the same time. Along the lines of the answer by #littlechris and for a more general solution that solves for times that have a minute, seconds, milliseconds component, you could use this function to count the number of milliseconds from the start of the day.
Create Function [dbo].[MsFromStartOfDay] ( #DateTime datetime )
Returns int
As
Begin
Return (
( Datepart( ms , #DateTime ) ) +
( Datepart( ss , #DateTime ) * 1000 ) +
( Datepart( mi , #DateTime ) * 1000 * 60 ) +
( Datepart( hh , #DateTime ) * 1000 * 60 * 60 )
)
End
I've verified that it returns the same int for two different dates with the same time
declare #first datetime
set #first = '1900-01-01 23:59:39.090'
declare #second datetime
set #second = '2000-11-02 23:56:39.090'
Select dbo.MsFromStartOfDay( #first )
Select dbo.MsFromStartOfDay( #second )
This solution doesn't always return the int you would expect. For example, try the below in SQL 2005, it returns an int ending in '557' instead of '556'.
set #first = '1900-01-01 23:59:39.556'
set #second = '2000-11-02 23:56:39.556'
I think this has to do with the nature of DateTime stored as float. You can still compare the two number, though. And when I used this approach on a "real" dataset of DateTime captured in .NET using DateTime.Now() and stored in SQL, I found that the calculations were accurate.
TL;DR
Separate the time value from the date value if you want to use indexes in your search (you probably should, for performance). You can: (1) use function-based indexes or (2) create a new column for time only, index this column and use it in you SELECT clause.
Keep in mind you will lose any index performance boost if you use functions in a SQL's WHERE clause, the engine has to do a scan search. Just run your query with EXPLAIN SELECT... to confirm this. This happens because the engine has to process EVERY value in the field for EACH comparison, and the converted value is not indexed.
Most answers say to use float(), convert(), cast(), addtime(), etc.. Again, your database won't use indexes if you do this. For small tables that may be OK.
It is OK to use functions in WHERE params though (where field = func(value)), because you won't be changing EACH field's value in the table.
In case you want to keep use of indexes, you can create a function-based index for the time value. The proper way to do this (and support for it) may depend on your database engine. Another option is adding a column to store only the time value and index this column, but try the former approach first.
Edit 06-02
Do some performance tests before updating your database to have a new time column or whatever to make use of indexes. In my tests, I found out the performance boost was minimal (when I could see some improvement) and wouldn't be worth the trouble and overhead of adding a new index.

Limiting a date range with exactness in MS SQL / SQL Server 2005

I want to limit a report to return records from Date A through Date B. This is what I have been doing:
declare #startDate varchar(20)
declare #endDate varchar(20)
set #startDate = '01/01/2008'
set #endDate = '04/01/2008'
-- test what are the start and end dates
select min(date),max(date) from view_Inspections
where date between #startDate and #endDate
... which I was told returned records from 12 am Jan 1st through 11:59 pm March 31st (that midnight is the default when no time is indicated). But I noticed a discrepancy, which is if a record has a time of 00:00:00 that it will be part of this set.
Is there a more exact way of doing this so it will return exactly the date range I want?*
I tried using time:
declare #startDate varchar(20)
declare #endDate varchar(20)
set #startDate = '01/01/2008 00:00:00'
set #endDate = '04/01/2008 11:59:59'
-- test what are the start and end dates
select min(date),max(date) from view_Inspections
where date between #startDate and #endDate
... but I noticed something wonky: SQL Server will ROUND the hundreth-second up by half. So I get that April 1st record (ha! April Fool's record! grr) if I use any time later than 11:59:29. Why is that?
(I feel sure there is. I'm new at this. Thanks for your help!)
There's always the easy option:
declare #startDate varchar(20)
declare #endDate varchar(20)
set #startDate = '01/01/2008'
set #endDate = '04/01/2008'
-- test what are the start and end dates
select min(date),max(date) from view_Inspections
where date >= #startDate
and date < #endDate
I suspect that the date column in view_Inspections is a SmallDateTime data type. This data type has 1 minute accuracy, which explains your unexpected results (rounding the seconds to the nearest minute).
The method Roland Shaw suggests is the best way to modify your query to accommodate your requirements.
The BETWEEN operator is inclusive, which is why you're seeing the results that you are in your first query. The rounding that you're seeing in your second query is going to be dependent on what exact datetime data type you are using in your table. (BTW, I think you're confusing seconds with hundredths of seconds). It looks like you're probably using a smalldatetime in your table, in which case the time is rounded to the nearest minute.
If your table is using datetime, try explicitly converting your #startDate and #endDate to DATETIME values (CAST(#endDate AS DATETIME)).
A quick note... even for DATETIME values, SQL Server is only accurate to the 3/100ths of a second, so 11:59:59.999 will get rounded up to 12:00:00.000.
You basically have three choices:
1) BETWEEN CAST('01/01/2008 00:00:00.000' AS DATETIME) AND CAST('03/31/2008 12:59:59.997' AS DATETIME)
2) YEAR(my_date) = 2008 AND MONTH(my_date) BETWEEN 1 AND 3
3) my_date >= CAST('01/01/2008 00:00:00.000' AS DATETIME) AND my_date < CAST('04/01/2008 00:00:00.000' AS DATETIME)
The first method isn't very intuitive and is error-prone in my opinion. The second method kills performance since indexes can't be used and it becomes much more complex if you can have searches that span years or begin/end in the middle of months. The third method, which Rowland suggested, is the best I think.
Simply try removing the time from the date field like so:
declare #startDate varchar(20)
declare #endDate varchar(20)
set #startDate = '01/01/2008'
set #endDate = '04/01/2008'
SELECT min(date),max(date) FROM view_Inspections
WHERE CAST(FLOOR(CAST(date AS FLOAT)) AS DATETIME) BETWEEN CAST(#startDate AS DATETIME) And CAST(#startDate AS DATETIME))
This will return everything from 01/01/2008 00:00:00 to 04/01/2008 11:59:59.999.
If you don't want 04/01 included, change your end date to 03/31/2008.
Your best solution is just create a BIGINT(10) field that called "julian", and store it in YYYYMMDD.
Then do the query
where julian >= '20120103' AND julian <= '20120203'