SQL Server where clause using In() vs Wildcard - sql-server

Is there any performance difference between query A and query B?
Query A
SELECT * FROM SomeTable
WHERE 1 = 1 AND (SomeField LIKE '[1,m][6,e][n]%')
Query B
SELECT * FROM SomeTable
WHERE 1 = 1 AND (SomeField IN ('16', 'Mens'))

The first could be much slower. An index can't be used with LIKE unless there is a constant prefix, for example LIKE 'foo%'. The first query will therefore require a table scan. The second query however could use an index on SomeField if one is available.
The first query will also give the wrong results as it matches '1en'.

Related

Why limit 2 result is not a superset of limit 1 result?

I created a temp table in snowflake and query it with the following command
select mykey
from myDB
limit 1;
The query returns result 'X'
Then I use the following command
select mykey
from myDB
limit 2;
The query returns result 'Y' and 'Z'. Question:
Why the result returned from the second query is not a superset of the result from first query?
You have no ORDER BY clause, thus your data is not forced into a stable sorted order, thus the limit may not be looking at the same rows.

sql select (..) where id in (list_of_values) vs select (...) where id in (subquery)

This is my first post on Stackoverflow. :-)
I use an SQL server, which has a huge table (up to 50'000'000 records), and a smaller table (up to 500'000 records).
Let's consider two queries:
Query A
SELECT *
FROM my_huge_table
WHERE column_name IN(list_of_values)
versus Query B
SELECT *
FROM my_huge_table
WHERE column_name IN (
SELECT column_name
FROM smaller_table
WHERE ...
)
The subquery in query B returns exactly the same list as list_of_values in query A.
The length of list_of_values in query A is limited (as described in many places on web). If my list_of_values is long (eg: 10'000), I have to split it into chunks, but when I use query B, it works fine, although results from the subquery from query B also contains 10'000 records...
What is more when I use query B, it is faster than query A. I looked into execution plans and it shows that query B uses some parallel calculations (I'm not familiar with execution plans).
Questions
In my script I have a list of values, I cannot easily create a subquery. Is there any way to execute something similar to query B using list of values?
Why is query B faster than query A?
Are there any other optimizations to be done?
PS: I've already created an index on the queried column.
Thanks.

T-SQL not equal operator vs Case statement

Assume I have a T-SQL statement:
select * from MyTable
where Code != 'RandomCode'
I've been tasked with making this kind of where statement perform more quickly. Books Online says that positive queries (=) are faster than negative (!= , <>).
So, one option is make this into a CASE statement e.g.
select * from MyTable
where
case when Code = 'RandomCode' then 0
else 1 end = 1
Does anyone know if this can be expected to be faster or slower than the original T-SQL ?
Thanks in advance.
You have to be more specific at what information you are interested in the table and what are the possible values of the Code column. Then you can create appropriate indexes to speed up the query.
For example, if values in the Code column could only be one of 'RandomCode', 'OtherCode', 'YetAnotherCode', you can re-write the query as:
SELECT * FROM MyTable WHERE Code = 'OtherCode' OR Code = 'YetAnotherCode'
And of course you need an index on the Code column.
If you have to do an inequality query, you can change SELECT * to a more narrow query like:
SELECT Id, Name, Whatever FROM MyTable WHERE Code != 'RandomCode'
Then create an index like:
CREATE INDEX idx_Code ON MyTable(Code) INCLUDE (Id,Name,Whatever)
This can reduce I/O by replacing a table scan with an index scan.

LIKE vs CONTAINS on SQL Server

Which one of the following queries is faster (LIKE vs CONTAINS)?
SELECT * FROM table WHERE Column LIKE '%test%';
or
SELECT * FROM table WHERE Contains(Column, "test");
The second (assuming you means CONTAINS, and actually put it in a valid query) should be faster, because it can use some form of index (in this case, a full text index). Of course, this form of query is only available if the column is in a full text index. If it isn't, then only the first form is available.
The first query, using LIKE, will be unable to use an index, since it starts with a wildcard, so will always require a full table scan.
The CONTAINS query should be:
SELECT * FROM table WHERE CONTAINS(Column, 'test');
Having run both queries on a SQL Server 2012 instance, I can confirm the first query was fastest in my case.
The query with the LIKE keyword showed a clustered index scan.
The CONTAINS also had a clustered index scan with additional operators for the full text match and a merge join.
I think that CONTAINS took longer and used Merge because you had a dash("-") in your query adventure-works.com.
The dash is a break word so the CONTAINS searched the full-text index for adventure and than it searched for works.com and merged the results.
Also try changing from this:
SELECT * FROM table WHERE Contains(Column, "test") > 0;
To this:
SELECT * FROM table WHERE Contains(Column, '"*test*"') > 0;
The former will find records with values like "this is a test" and "a test-case is the plan".
The latter will also find records with values like "i am testing this" and "this is the greatest".
I didn't understand actually what is going on with "Contains" keyword. I set a full text index on a column. I run some queries on the table.
Like returns 450.518 rows but contains not and like's result is correct
SELECT COL FROM TBL WHERE COL LIKE '%41%' --450.518 rows
SELECT COL FROM TBL WHERE CONTAINS(COL,N'41') ---40 rows
SELECT COL FROM TBL WHERE CONTAINS(COL,N'"*41*"') -- 220.364 rows

sql server conditional where

select * from table where category=#categoryid
I'm not sure how easy is this but I couldn't get my head around it. I want to be able to change where clause on above query so that if use 0 instead of 1-2-3 or 4 as #categoryid it would select all categories. i don't have any category with 0 in database.
Simple.
select * from table where (category=#categoryid) OR (#categoryid = 0)
This should probably be divided into 2 separate queries unless you actually want the same execution plan of a full clustered index scan to be used both in the case that #categoryid=0 and #categoryid<>0
By dividing into 2 separate queries you will potentially allow the ones where #categoryid is not zero to be satisfied by an index seek rather than the full scan.
If the table is small or #categoryid is not very selective it might not be an issue however.
You can set it to NULL when you want to select all categories an just modify select like this
select * from table where category= ISNULL( #categoryid, category )
select * from table where
category BETWEEN #mincategoryid AND #maxcategoryid
Min and max will one of
both be 1 (or 2 or 3 or 4)
respectively 0 and a high number
This will use an index too..
This is SQL not PL/SQL.
You need to test the value before sending the request you can not ask to SQL test it for you.

Resources