How to ignore left padding in a LIKE statement? - sql

I'm modifying code for an ID search bar and I'm trying to enable the user to be able to search for ID's using SQL syntax, so for example '%535%'. Doing just that is simple enough, but I've been searching and racking my brains for a while now and I can't seem to find a solution to the issue described below:
The problem is that the IDs are all left-padded varchar(14), as in:
' 8534'
' 393583'
' 123456/789'
This virtually disables the user from searching only for IDs that begin with a certain sequence, as '85%' returns no results due to the whitespace padding.
The site I'm maintaining is an oldie written in classic ASP (w/ JScript) and the search is done via a stored procedure with the whole 'WHERE' clause being passed in as a parameter.
I'm not able to modify the database, so what I"m asking is: is there any way to modify the clause so that the padding is ignored and '52%' returns IDs beginning with 52?

You want:
where ltrim(id) like '123%'
or, assuming that there are no interior spaces in the id:
where concat(' ', id) like '% 123%'

SELECT LTRIM(ID) FROM table WHERE ID LIKE '%1234%'
Edit as you can only modify WHERE statement
WHERE LTRIM(ID) LIKE '1234%'

Functions in the where clause tend to be slow. Something like this might be quicker:
where id like '123%'
or id like '% 123%'

Related

Need a way of finding special characters in data using SQL query

I am trying to find special characters in any of my fields that are not in the range of a-zA-Z0-9. However if I try this query:
select Name from table where Name like '%[?]%'
I get two records:
???? ?????
Fixed?????
Which is what I want. However, since I don't know what the special chars will be I need to use an exclusion of data that has mixed characters:
select Name from table where Name NOT like '%[a-zA-Z0-9]%'
Since this excludes all records with a-zA-Z0-9 I only get:
???? ?????
But I also need to get the 'Fixed?????' result. I need to get the data that has the special character merged into it.
I am bit at a loss as how to do this. I've seen this done with shell scripts or 'vi' (LIST), but in SQL that's not so easy.
Has anyone out there solved this?
Try this code:
select Name from table where Name like '%[^0-9a-zA-Z ]%'
Thank you for replying. I had tried your suggestions but I was still getting more results. However, it looks like you can get very specific with the exclusion. Eventually I ended up adding results from the data I got.
Like this:
select Name from table where Name LIKE '%[^0-9a-zA-Z() -._/\:=,]%'
This finally gave me what I was looking for. Although new issue I have now is how to suppress the [] brackets which apparently also are found in the data:
???? ?????
HP PCI 10/100Base-TX Core [100BASE-TX,FD,AUTO,TT=1500]
Fixed?????
Adding those brackets into the query breaks the array boundary:
'%[^0-9a-zA-Z() -._/\:=,**[]**]%'
However, this is something I can handle. As long as I am not getting "all" the data.
LIKE '%[^0-9a-zA-Z]%'
numbers (0-9), lowercase alphas (a-z), uppercase alphas (A-Z). The "^" makes that a "NOT" one of these things

Extensive String Manipulation - Cursor or While-Loop?

Quick Background
I have received a project from our marketing team to make bulk updates to the descriptions of products that will be displayed on our website (>500k items). They have decided to take many decades worth of descriptions and try to make them as similar as possible. (Ex. 'screw driver', 'screwdriver', 'screw-driver' should all look like 'Screwdriver')
I successfully accomplished the task at hand to 95% of their satisfaction using a clunky, long and hard to maintain series of update statements on a table only I maintain, to modify the strings. I then pass these on to our web deployment team, but wasn't thinking they would want to maintain this indefinitely.
I can easily produce a table of sub-strings and conditions to find and what to replace portions of the string. I think something depending on a table like this would be easiest to maintain for 90% of the cases we encounter.
Now, I'm uncertain about the best way to proceed to make this dependable and easy to maintain. I've received conflicting information that a good use would be a 'while loop' and other say a Cursor would be just fine.
Now to the question
Given we will/may/could be adding somewhere around 1k new products a month, and I have a table of conditions like the following, what is the most efficient and dependable way to execute the manipulation regularly?
Condition, Find_substring, Replace_with
like '%screw driver%', 'screw driver', 'Screwdriver'
like '%screw-driver%', 'screw driver', 'Screwdriver'
like '%screwdriver%', 'screwdriver', 'Screwdriver'
Open to any and all ideas, suggestions and advice.
If your rules are really as simple as that then simply having "old_value" and "new_value" in the table should suffice, with a single statement to fix all of the data:
UPDATE
MT
SET
description = REPLACE(description, old_value, new_value)
FROM
dbo.My_Table MT
INNER JOIN dbo.Fix_Table FT ON MT.description LIKE '%' + FT.old_value + '%'
You might need to adjust the query if you expect multiple matches on a single product. Also, be careful of strings that might be part of another string. For example, fixing "ax" to "axe" might cause problems with a "fax machine". There are a lot of little details like this that might affect the exact approach.
Have a table like bad_val and good_val (call it tblMod). you can write a stored procedure that loops on tblMod and generate SQL statement and execute the statement as dynamic SQL.
loop on tblMod
-- generate SQL statements like:
set sqlText = 'update myTable set description = ' + good_val + ' where description = ' + bad_val
sp_execute sqlText
This approach also allows you to use SQL functions or any other functions in good_val field of tblMod. for instance you can have below data in good_val field: 'upper(description)'
or 'substring(description, 1 ,4)'
as you are generating dynamic SQL, those will work.
in this case your sqlText will be something like
'update myTable set description = substring(description, 1, 4) where description = 'some bad value'
example above might not be correct but I hope you get my idea.

Is there an alternation for wildcards using LIKE in T-SQL?

My query looks for dataset containing a particular label, let say:
SELECT * FROM Authors
WHERE Title LIKE #pattern
where #pattern is defined by user. So, %abc% would match abcd, 0abc, etc. Sometimes there are labels like
Xabc-ONE
blaYabc-TWO-sometext
Zabc-THREE
blubXabc-FOUR
and I'm looking for labels containing abc and ONE or TWO, something like %abc%(ONE|TWO)%. Is it possible?
You can add support for regular expressions to SQL Server via a CLR function, as shown in this answer, but it may not be possible for you in your environment. Check with your friendly sysadmin!
Maybe I don't understand your question right, but why not simply
SELECT * FROM Authors
WHERE Title LIKE '%abc%ONE%' OR '%abc%TWO%'
?
LIKE is just a search with wildcards, nothing more, so there's actually no other way of doing what you want with LIKE. If you need more, have a look into regular expressions. But be aware that it's slower than LIKE and in your case absolutely not necessary.
UPDATE:
From comments "don't want to care for what the user wants to match"...then simply do it like this:
SELECT * FROM Authors
WHERE Title LIKE CONCAT('%', $userInput, '%ONE%') OR CONCAT('%', $userInput, '%TWO%')
Or do I still don't get you right?
If you are using SQL Server you can enable the full text search engine and use the keyboards contains and near to find abc near ONE
I will say in the query(pseudo code)
Select something from table where CONTAINS(column_name, 'abc NEAR ONE')
http://msdn.microsoft.com/en-us/library/ms142568.aspx

Match comma separated values in column

If I have a column called 'Categories' with say science,maths,english in the row comma-separated as shown, how would I match all rows with the category containing maths?
I've tried a simple LIKE but it is not quite accurate as there may be 'poo_science' which when searching for '%science%' would match both.
I've looked around StackOverflow and there are plenty of similar questions but all seem to want to return data as a comma separated list or something - not quite what I'm after.
I'd prefer not to use a stored procedure and cannot use full-text searching. I have a stored procedure I used which added another character ('$') around each value and then would search for '$value$'... is this too nasty? I'm after a little more simple method.
Disclaimer: The commentators are right... CSVs in a single field are a horrible design, and should be re-done.
With that said, here's how you can work around your problem:
Pad Categories with leading and trailing ,, that way you can include them in your wildcard search:
WHERE (',' + Categories + ',') LIKE '%,science,%'
Use FIND_IN_SET(,)
SQL:
SELECT name FROM orders,company
WHERE orderID = 1
AND
FIND_IN_SET(companyID, attachedCompanyIDs)
or
can check this link FIND_IN_SET() vs IN()
I propose a 4x WHERE that can match any of the possible cases: value alone, value at the start, middle or end of the csv:
WHERE Categories = 'science' /* CSV containing only the one value */
OR Categories LIKE 'science,%' /* value at start of CSV */
OR Categories LIKE '%,science,%' /* value somewhere in the middle */
OR Categories LIKE '%,science' /* value at the end of CSV */
This way all 'science' rows should be selected but none of the 'poo_science' rows.
I've made some assumptions about your data layout. Try this - using SQL Server 2K8+ this should work:
DECLARE #SearchString NVarChar(100) = 'maths';
SELECT 1 SomeId, 'science,maths,english' Categories
INTO #TestTable;
WITH R AS (
SELECT
X.SomeId,
C.value('#value', 'NVarChar(100)') SomeTagValue
FROM (SELECT SomeId,
CONVERT(XML, '<tag value = "' + REPLACE(Categories, ',', '" /><tag value = "') + '" />') XMLValue
FROM #TestTable) X CROSS APPLY X.XMLValue.nodes('//tag') T(C)
)
SELECT *
FROM R
WHERE SomeTagValue = #SearchString;
DROP TABLE #TestTable;
It's definitely not going to be super-efficient or very scalable, but then working against denormalized data tends to inherently have those issues.
This question is visible on google and has many views, so I want to share my approach to this problem. I had to deal with such a poor design as comma-separated values stored as strings too. I came across this issue while tweaking a CMS's plugin responsible for tags.
Yeah, tags related to a site article were stored like this: "tag1,tag2,...,tagN". So, getting the exact match wasn't as trivial as it might have initially appeared: using simple LIKE, with articles tagged "ball" I also got ones tagged "football" and "ballroom". Not critical, but rather annoying.
FIND_IN_SET function seemed awesome at first but then it turned out that it doesn't use index and doesn't work properly if the first argument contains a comma character.
I had no desire to alter the plugin itself or deeper CMS core functionality which that plugin had been built upon.
Also it is worth noting that needed tag (substring) can be the first, the last element in the string or can be somewhere in the middle, so this piece of code WHERE (',' + Categories + ',') LIKE '%,science,%' doesn't cover all three cases.
Finally, I ended up with very simple solution. It worked for me like this:
... WHERE tags LIKE 'ball,%' OR tags LIKE '%,ball,%' OR tags LIKE '%,ball'
All theree cases covered; commas used as delimiters. Hope it helps others who came across similar pitfall.
PS. I am not a MySQL/DB expert at all and I would love to read about potential drawbacks of this approach especially on really huge tables (which wasn't my case, btw). I just shared the results of my small research and what I did to solve this problem with minimal efforts.
use FIND_IN_SET() mysql function
Syntax
SELECT * FROM as a WHERE FIND_IN_SET(value to search in string,comma separated string);
Example
SELECT * FROM as a WHERE FIND_IN_SET(5,"1,2,3,4,5,6");
More Information Follow Below Link :
http://blog.sqlauthority.com/2014/03/21/mysql-search-for-values-within-a-comma-separated-values-find_in_set/

Using LIKE with domestic language in SQL

I am using a SQL Server database, and I am storing Malayalam names in my tables. I just want to write a query for filtering names using some Malayalam words.
SELECT * FROM table WHERE mal_Name LIKE '#word%'
#word contain Malayalam words.
How can I achieve this? Please share any ideas.
EDIT
This is my table, rm_Malayalam_name contains Malayalam name. And my Query is
SELECT *
FROM Purchase.tblRawMaterials
WHERE rm_malayalam_name LIKE '%കദളിപഴം%'
It doesn't work. The entry is there but while executing this query nothing is shown
Do you mean you want to do something like SELECT * FROM table WHERE mal_Name LIKE '%'+#word+'%'
This will work if #Word is a single word, however if you want to take in multiple words you are going to need something a bit more complex.
UPDATE:
Having seen your new edits I would suspect that the reason it is not selecting is due to the encoding
Try SELECT * FROM table WHERE mal_Name LIKE N'%'+#word+'%'
or
select * from Purchase.tblRawMaterials where rm_malayalam_name like N'%കദളിപഴം%'
I'd suggest reading up on SQL's full-text search It will almost certainly be more efficient than LIKE '%word%'
How many words will you be searching on? How big is the column? These factors might influence what the best option is.