SQL Contains Question - sql

Can someone explain this to me? I have two queries below with their results.
query:
select * from tbl where contains([name], '"*he*" AND "*ca*"')
result-set:
Hertz Car Rental
Hemingyway's Cantina
query:
select * from tbl where contains([name], '"*he*" AND "*ar*"')
result-set:
nothing
The first query is what I would expect, however I would expect the second query to return "Hertz Car Rental". Am I fundamentally misunderstanding how '*' works in full-text searching?
Thanks!

I think SQL Server is interpreting your strings as prefix_terms. The asterisk is not a plain old wildcard specifier. Fulltext and Contains are word oriented. For what you are trying to do, you would be better off using plain old LIKE instead of CONTAINS.
http://msdn.microsoft.com/en-us/library/ms187787.aspx

"*" only works as a suffix. If you use it as a prefix, the table needs to be scanned no matter what and the index is useless. At that point, you might as well do
Select * From Table Where (Name Like '%he%') And (Name Like '%ar%')

I would try replacing * with % to see how it goes.
select * from tbl where contains([name], '"%he%" AND "%ar%"')

Related

SQL code for retrieving values of column starting using wildcard

I want to look for values in variable/column which start with 'S' and has 'gg' in between.
For instance Staggered is a word which starts with alphabet S and has gg in between the word.
so what sql query to write to get the result.
Due to the fact that you did not provide much meta information (which database?), I'll just show the following:
SELECT * FROM <table>
WHERE <columnname> LIKE 'S%gg%';
Good luck :)
As the target database is not mentioned, I will answer with Oracle syntax:
select *
from TABLE_NAME
where COL_NAME like 'S%gg%'

Sql LIKE in Arabic?

Consider this sample:
CREATE TABLE #tempTable
(name nvarchar(MAX))
INSERT INTO #tempTable VALUES (N'إِبْرَاهِيمُ'), (N'إبراهيم')
SELECT * FROM #tempTable WHERE name = N'إبراهيم'
SELECT * FROM #tempTable WHERE name LIKE N'%إبراهيم%'
Both selects only return إبراهيم but not إِبْرَاهِيمُ. How can I make it ignore these non-alphabetical characters in search? In other words, I want to get all similar words, including those with non-alpha characters.
You do not do it. Simple. NOTHING about arabic here - you have the same problem in english.
How can I make it ignore these non-alphabetical characters in search?
Like numbers? NOT AT ALL. Not with "standard SQL Syntax".
If you can, put a full text index on the field. And use the full text search syntax in your query. This is what it is for.
There is a thread over at sql stackexchange that has a workaround for this issue.
https://dba.stackexchange.com/questions/14153/treating-certain-arabic-characters-as-identical
Unfortunately, there is no case sensitive Arabic language, and of course, both select statements will return 'إبراهيم' because they were ordered to do that.
This is a problem we have been suffering from for a very long time, people always look for 'احمد' when it's written 'أحمد' and they won't find it.
this is a solution 100%:
$yourChaine = \Transliterator::create('NFC; [:Nonspacing Mark:] Remove; NFC')
->transliterate($yourChaine);

One select for multiple records by composite key

Such a query as in the title would look like this I guess:
select * from table t where (t.k1='apple' and t.k2='pie') or (t.k1='strawberry' and t.k2='shortcake')
... --10000 more key pairs here
This looks quite verbose to me. Any better alternatives? (Currently using SQLite, might use MYSQL/Oracle.)
You can use for example this on Oracle, i assume that if you use regular concatenate() instead of Oracle's || on other DB, it would work too (as it is simply just a string comparison with the IN list). Note that such query might have suboptimal execution plan.
SELECT *
FROM
TABLE t
WHERE
t.k1||','||t.k2 IN ('apple,pie',
'strawberry,shortcake' );
But if you have your value list stored in other table, Oracle supports also the format below.
SELECT *
FROM
TABLE t
WHERE (t.k1,t.k2) IN ( SELECT x.k1, x.k2 FROM x );
Don't be afraid of verbose syntax. Concatenation tricks can easily mess up the selectivity estimates or even prevent the database from using indexes.
Here is another syntax that may or may not work in your database.
select *
from table t
where (k1, k2) in(
('apple', 'pie')
,('strawberry', 'shortcake')
,('banana', 'split')
,('raspberry', 'vodka')
,('melon', 'shot')
);
A final comment is that if you find yourself wanting to submit 1000 values as filters you should most likely look for a different approach all together :)
select * from table t
where (t.k1+':'+t.k2)
in ('strawberry:shortcake','apple:pie','banana:split','etc:etc')
This will work in most of the cases as it concatenate and finds in as one column
off-course you need to choose a proper separator which will never come in the value of k1 and k2.
for e.g. if k1 and k2 are of type int you can take any character as separator
SELECT * FROM tableName t
WHERE t.k1=( CASE WHEN t.k2=VALUE THEN someValue
WHEN t.k2=otherVALUE THEN someotherValue END)
- SQL FIDDLE

Make an SQL request more efficient and tidy?

I have the following SQL query:
SELECT Phrases.*
FROM Phrases
WHERE (((Phrases.phrase) Like "*ing aids*")
AND ((Phrases.phrase) Not Like "*getting*")
AND ((Phrases.phrase) Not Like "*contracting*"))
AND ((Phrases.phrase) Not Like "*preventing*"); //(etc.)
Now, if I were using RegEx, I might bunch all the Nots into one big (getting|contracting|preventing), but I'm not sure how to do this in SQL.
Is there a way to render this query more legibly/elegantly?
Just by removing redundant stuff and using a consistent naming convention your SQL looks way cooler:
SELECT *
FROM phrases
WHERE phrase LIKE '%ing aids%'
AND phrase NOT LIKE '%getting%'
AND phrase NOT LIKE '%contracting%'
AND phrase NOT LIKE '%preventing%'
You talk about regular expressions. Some DBMS do have it: MySQL, Oracle... However, the choice of either syntax should take into account the execution plan of the query: "how quick it is" rather than "how nice it looks".
With MySQL, you're able to use regular expression where-clause parameters:
SELECT something FROM table WHERE column REGEXP 'regexp'
So if that's what you're using, you could write a regular expression string that is possibly a bit more compact that your 4 like criteria. It may not be as easy to see what the query is doing for other people, however.
It looks like SQL Server offers a similar feature.
Sinec it sounds like you're building this as you go to mine your data, here's something that you could consider:
CREATE TABLE Includes (phrase VARCHAR(50) NOT NULL)
CREATE TABLE Excludes (phrase VARCHAR(50) NOT NULL)
INSERT INTO Includes VALUES ('%ing aids%')
INSERT INTO Excludes VALUES ('%getting%')
INSERT INTO Excludes VALUES ('%contracting%')
INSERT INTO Excludes VALUES ('%preventing%')
SELECT
*
FROM
Phrases P
WHERE
EXISTS (SELECT * FROM Includes I WHERE P.phrase LIKE I.phrase) AND
NOT EXISTS (SELECT * FROM Excludes E WHERE P.phrase LIKE E.phrase)
You are then always just running the same query and you can simply change what's in the Includes and Excludes tables to refine your searches.
Depending on what SQL server you are using, it may support REGEX itself. For example, google searches show that SQL Server, Oracle, and mysql all support regex.
You could push all your negative criteria into a short circuiting CASE expression (works Sql Server, not sure about MSAccess).
SELECT *
FROM phrases
WHERE phrase LIKE '%ing aids%'
AND CASE
WHEN phrase LIKE '%getting%' THEN 2
WHEN phrase LIKE '%contracting%' THEN 2
WHEN phrase LIKE '%preventing%' THEN 2
ELSE 1
END = 1
On the "more efficient" side, you need to find some criteria that allows you to avoid reading the entire Phrases column. Double sided wildcard criteria is bad. Right sided wildcard criteria is good.

MySQL question about "reverse LIKEs"

Well given I have a value I want to check for potential matches in a database (in one varchar field) so I write something like:
SELECT * FROM table WHERE column LIKE "%value%"
Which will work if the value is something like "test" and the column has a value of "this is a test" however if it is reversed then I will not get a match I have tried things along the lines of:
SELECT * FROM table WHERE CONCAT("%",column,"%") LIKE "value"
but don't know exactly how to phrase this to Google to get a response I need, please help!
You can reverse a like statement. Just using the same syntax as a regular like query:
select
*
from
table
where
'value' like concat('%', column, '%')
Of course, if you felt wild and crazy, you could also use instr:
select * from table where instr('value', column) > 0
I don't know which one is faster, since I don't have a MySQL instance to test against, but it's worth trying both to see which wins.
SELECT *
FROM table
WHERE 'value' LIKE CONCAT('%', column, '%')