473,657 Members | 2,546 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Rewrite a WHERE clause

I have a WHERE clause that could be an "=" or a "LIKE" depending upon
if the passed variable is populated or not. I would like to know the
best way to write the WHERE clause to make it dynamically switch
between the 2 and make best use of the indexes.

CREATE TABLE myTable(ID INT PRIMARY KEY CLUSTERED, COUNTY VARCHAR(50))
CREATE INDEX IDX_myTable_Cou nty ON myTable(COUNTY)

DECLARE @COUNTY VARCHAR(50)
SET @COUNTY = 'SANTA CLARA' -- Could also be SET @COUNTY = NULL

SELECT ID FROM myTable
WHERE COUNTY LIKE (CASE WHEN @COUNTY IS NOT NULL THEN @COUNTY ELSE '%'
END)

This does not seem like best practice to me because I am forced to use
"LIKE" even when @COUNTY is populated with data. Ultimately I'd like:

WHERE (CASE WHEN @COUNTY IS NOT NULL COUNTY = @COUNTY ELSE COUNTY LIKE
'%' END)

but that is incorrect syntax on "=".

Also, I do not want to use a dynamically built statement. Is there a
way around this?

Thanks,
Josh

Aug 29 '05 #1
14 3260
Hello, Josh

See this article by Erland Sommarskog, SQL Server MVP:
http://www.sommarskog.se/dyn-search.html#Umachandar
There are some solutions in the article that are not using Dynamic SQL.

Razvan

Aug 29 '05 #2
Josh,

You might try this, if your data is all typical alphabetic
values in English (no letters of the alphabet that come
after Z). I'm also assuming your collation is case-insensitive.

where COUNTY >= coalesce(@COUNT Y,'A')
and COUNTY <= coalesce(@COUNT Y,'ZZZZZZZZZZZZ ZZZZZZZ')
-- as many Z's as the declared length of the COUNTY column

This may be more efficient than your LIKE solution, but the
only way to be certain is to do some comparisons. You also
run the risk in situations like this of getting bad cached
query plans, at least if your actual query selects more than
the ID column, since the best query plan for @COUNTY = NULL
is a table scan and the best query plan for @COUNTY <> NULL
is a non-clustered index seek followed by a bookmark lookup.
If the second plan is cached and used later when @COUNTY is
NULL, it will be very inefficient. A way around this, should
it occur, may be to add something to force query recompilation.
In a stored procedure, that might be adding WITH RECOMPILE,
or in an sp or otherwise, adding something to the query that
will prevent autoparameteriz ation (adding AND 1 = 1 to the
WHERE clause will do this, I believe)

Maybe that's more than you needed to know, but your question
suggests you are thinking about some important considerations
in query design.

Steve Kass
Drew University

joshsackett wrote:
I have a WHERE clause that could be an "=" or a "LIKE" depending upon
if the passed variable is populated or not. I would like to know the
best way to write the WHERE clause to make it dynamically switch
between the 2 and make best use of the indexes.

CREATE TABLE myTable(ID INT PRIMARY KEY CLUSTERED, COUNTY VARCHAR(50))
CREATE INDEX IDX_myTable_Cou nty ON myTable(COUNTY)

DECLARE @COUNTY VARCHAR(50)
SET @COUNTY = 'SANTA CLARA' -- Could also be SET @COUNTY = NULL

SELECT ID FROM myTable
WHERE COUNTY LIKE (CASE WHEN @COUNTY IS NOT NULL THEN @COUNTY ELSE '%'
END)

This does not seem like best practice to me because I am forced to use
"LIKE" even when @COUNTY is populated with data. Ultimately I'd like:

WHERE (CASE WHEN @COUNTY IS NOT NULL COUNTY = @COUNTY ELSE COUNTY LIKE
'%' END)

but that is incorrect syntax on "=".

Also, I do not want to use a dynamically built statement. Is there a
way around this?

Thanks,
Josh

Aug 29 '05 #3
Thanks to both of you for your suggestions. I will try your methods and
see which is actually faster and which grabs the correct query plan
every time.

Aug 29 '05 #4
SQL programmers tend to trust the optimizer rather than write programs
that change on the fly. We also like the easiest to read form of
identical expressions:

county LIKE COALESCE (@my_county, '%')

Go with this and let the compiler figure out if the parameter is a
NULL, a string or a pattern. The LIKE predicate generates a simple
finite state machine to parse a string using the pattern given. The
state machine for '%' is very fast.

Aug 29 '05 #5
AK
I would keep things simple

if @COUNTY is NULL
--------- scan the table
select * from some_table
else
-------- might use an index
select * from some_table where conty = @county
end if

this way you'll have 2 precompiled plans for 2 different cases

Aug 29 '05 #6
--CELKO-- (jc*******@eart hlink.net) writes:
SQL programmers tend to trust the optimizer rather than write programs
that change on the fly. We also like the easiest to read form of
identical expressions:

county LIKE COALESCE (@my_county, '%')

Go with this and let the compiler figure out if the parameter is a
NULL, a string or a pattern. The LIKE predicate generates a simple
finite state machine to parse a string using the pattern given. The
state machine for '%' is very fast.


On SQL 2000 this is a very poor advice. The query will table scan in
all cases. It should scan if @my_count is NULL of course. The optimizer
does not know when it builds the plan which value @my_county will have,
so it must have a plan that handles any value.

In SQL 2005 you can add the query hint

OPTION (RECOMPILE)

to get statement recompilation of that query only. In this case, it
will pick the plan which matches the value of @my_county best - or at
least I expect it two.

--
Erland Sommarskog, SQL Server MVP, es****@sommarsk og.se

Books Online for SQL Server SP3 at
http://www.microsoft.com/sql/techinf...2000/books.asp

Aug 29 '05 #7
just add "= 1" to the end

here is a working example:
where (case when @arg is null then
case when
[property_id] = 1 //put your test when @arg is null here
then 1 else 0 end
else
case when
[property_id] = 2 //and your other one here
then 1 else 0 end
end) = 1

Aug 30 '05 #8
to explain

we are using case when <boolean> then 1 else 0 end

to get around sql servers strict handling of boolean type

then converting back from 1 > true and 0 > false at the end

you can't directly use "where case (blah)" because case doesn't return
a boolean value
but you can use "where case (blah) = 1" to convert the value coming out
of case to a boolean value

Aug 30 '05 #9
I thought that 2005 was geting a "multi-plan" feature like DB2. It
actually saves multiple exection plans and effectively does what AK
proposed, but without you having to tell it. Do you know if the OPTION
(RECOMPILE) discards or saves prior plans?

Aug 30 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
21995
by: A.V.C. | last post by:
Hello, I found members of this group very helpful for my last queries. Have one problem with CASE. I can use the column name alias in Order By Clause but unable to use it in WHERE CLAUSE. PLS TELL ME IF IT IS POSSIBLE TO USE IT IN WHERE CLAUSE AND SOME ALTERNATIVE. QUERY: SELECT
3
1895
by: kalamantina | last post by:
How to rewrite this snippet if you must implement IDisposable private static void OpenConnection() { string connectionString = GetConnectionString(); StringBuilder errorMessages = new StringBuilder();
14
1812
by: Stan Canepa | last post by:
This post is mostly for discussion. Why rewrite in .NET? Just a general discussion not related to any specific details. I was just looking to see what reasons developers are looking to, to help decide whether they should rewrite their app in .NET. What are the trends being observed of Microsoft when it comes to .Net? How much longer will COM objects live on? How stable is the Framework?
2
10747
by: Jim.Mueksch | last post by:
I am having a problem with using calculated values in a WHERE clause. My query is below. DB2 gives me this error message: Error: SQL0206N "APPRAISAL_LESS_PRICE" is not valid in the context where it is used. SQLSTATE=42703 SELECT DISTINCT S3.OPR_APPLICATION_NR, S3.APPLICATION_ID, S3.APPRAISAL_TYPE_CD, S3.Appraisal_Used_Amount, S3.RPT_LEVEL2_NR,
9
19139
by: Emin | last post by:
Dear Experts, I have a fairly simple query in which adding a where clause slows things down by at least a factor of 100. The following is the slow version of the query ------------------------- SELECT * FROM ( Select x.event_date From x FULL OUTER JOIN y ON x.event_date = y.event_date
8
3475
by: chrisdavis | last post by:
I'm trying to filter by query or put those values in a distinct query in a where clause in some sort of list that it goes through but NOT at the same time. Example: ROW1 ROW2 ROW3 ROW4 , etc. I want to go to the first row, do a WHERE statement, return the
5
2655
by: pwiegers | last post by:
Hi, I'm trying to use the result of a conditional statement in a where clause, but i'm getting 1)nowhere 2) desperate :-) The query is simple: -------- SELECT idUser, (@ageraw:=YEAR(CURRENT_DATE()) - YEAR(dateofbirth) -
4
14265
by: Jane T | last post by:
I appreciate how difficult it is to resolve a problem without all the information but maybe someone has come across a similar problem. I have an 'extract' table which has 1853 rows when I ask for all rows where period_ = 3. The allocation table for info has 210 rows. I have two scripts below. The first script where I specify a period on a join, brings back 1853 lines and works. The second script where I specify the period in the...
3
1824
by: VGD | last post by:
"Serge Rielau" <srielau@ca.ibm.comescribió en el mensaje news:6e8m5mF5uf8oU1@mid.individual.net... Hello Serge I've checked that DB2 OS/390 8.1.5 accepts WITH clause but doesn't accept VALUES clause in the context I need.
0
8425
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8845
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
8522
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8622
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
7355
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
4333
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2745
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
1973
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
2
1736
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.