I want to create a mysql search query, that will search for postcodes here is what i have done so far
SELECT * FROM orders where ( InvoicePostcode LIKE 'b%' OR InvoicePostcode LIKE 'ws%') order by InvoiceNumber asc
I want to display only postcode starting with b or ws but the problem is some post contain bb or BS at the start of the postcode for example
BS24 8EE
BB9 8SY
the only ones that should be showing that start with b like this one B65 0NQ im not sure how to check postcode by only looking at the letter at the start before the numbers in the postcode
You can try to use regexp to exclude certain pattern:
In the below I exclude InvoicePostcode containing B followed by a letter
SELECT * FROM orders
WHERE (InvoicePostcode LIKE 'b%' AND NOT InvoicePostcode RLIKE '^(B[A-Z])')
OR (InvoicePostcode LIKE 'ws%' AND NOT InvoicePostcode RLIKE '^(WS[A-Z])')
ORDER BY InvoiceNumber ASC
You can use pattern matching to solve this issue.
What you need to know is the pattern you are searching for, to give you an example if you are searching for all postcodes starting with B only then you know that these postcodes will
Must have first character as B. There are examples in link to select first character (^) and 1 instance({1} equal to 'B' or 'b'.
Second character can be any number
Similarly you can do for all other patterns as well.
You can use REGEXP clause for the same.
E.g.:
select * from orders where (InvoicePostcode REGEXP '^B[^BS].' OR InvoicePostcode REGEXP '^WS.')
'^B[^BS].*' in this it will ignore words start with BB OR BS.
Hope it'll help you out.
SELECT * FROM orders
WHERE (InvoicePostcode LIKE 'b%' AND NOT InvoicePostcode RLIKE '^(B[A-Z])')
OR (InvoicePostcode LIKE 'ws%' AND NOT InvoicePostcode RLIKE '^(WS[A-Z])')
ORDER BY InvoiceNumber ASC
pls refer : https://www.guru99.com/regular-expressions.html
RLIKE operator performs a pattern match of a string expression against a pattern. The pattern is supplied as an argument. The following MySQL statement will find the author’s name beginning with ‘B’. The ‘^’ have been used to match the beginning of the name.
SELECT * FROM orders WHERE InvoicePostcode RLIKE '^B';
[A-Z]
Matches any uppercase letter
[a-z]
Matches any lowercase letter
'^(B[A-Z])'means it will work as first letter B and whether next is A to Z are not.
Related
I am making an eCommerce website I am using PHP and Mysql and I have some products name in table named product. How can I make a search system by which if I type "Wallnuts", it should return all results having word "wallnut, walnut, walnuts" and word with same pronunciation like "valnuts" and sorted as best matching result first. For this I am trying this by this query :
select product_name,photo,in_stock,sell_price
from $tbl_product
where product_name like '%".$q."%'
ORDER BY (CASE WHEN product_name LIKE '".$q."%' THEN 1
WHEN product_name LIKE '%".$q."%' THEN 2 ELSE 3
END) limit 0,10
Where $q is search string. By this query I am getting result but with only exact word match.
I need result like on Bigbasket.com for word wallnuts, wallnut, walnts, valnuts.
The closest you can try is SOUNDEX() function in MYSQL.
select * from mytext
where soundex(val) LIKE CONCAT('%',SOUNDEX('wallnut'),'%')
This gives me wallnuts, wallnut, walnts.Check Demo here
I've got a database table mytable with a column name in Varchar format, and column date with Datetime values. I'd like to count names with certain parameters grouped by date. Here is what I do:
SELECT
CAST(t.date AS DATE) AS 'date',
COUNT(*) AS total,
SUM(LENGTH(LTRIM(RTRIM(t.name))) > 4
AND (LOWER(t.name) LIKE '%[a-z]%')) AS 'n'
FROM
mytable t
GROUP BY
CAST(t.date AS DATE)
It seems that there's something wrong with range syntax here, if I just do LIKE 'a%' it does count properly all the fields starting with 'a'. However, the query above returns 0 for n, although should count all the fields containing at least one letter.
You write:
It seems that there's something wrong with range syntax here
Indeed so. MySQL's LIKE operator (and SQL generally) does not support range notation, merely simple wildcards.
Try MySQL's nonstandard RLIKE (a.k.a. REGEXP), for fuller-featured pattern matching.
I believe LIKE is just for searching for parts of a string, but it sounds like you want to implement a regular expression to search for a range.
In that case, use REGEXP instead. For example (simplified):
SELECT * FROM mytable WHERE name REGEXP "[a-z]"
Your current query is looking for a string of literally "[a-z]".
Updated:
SELECT
CAST(t.date AS DATE) AS 'date',
COUNT(*) AS total,
SUM(LENGTH(LTRIM(RTRIM(t.name))) > 4
AND (LOWER(t.name) REGEXP '%[a-z]%')) AS 'n'
FROM
mytable t
GROUP BY
CAST(t.date AS DATE)
I believe you want to use WHERE REGEXP '^[a-z]$' instead of LIKE.
You have regex in your LIKE statement, which doesn't work. You need to use RLIKE or REGEXP.
SELECT CAST(t.date AS DATE) AS date,
COUNT(*) AS total
FROM mytable AS t
WHERE t.name REGEXP '%[a-zA-Z]%'
GROUP BY CAST(t.date AS DATE)
HAVING SUM(LENGTH(LTRIM(RTRIM(t.name))) > 4
Also just FYI, MySQL is terrible with strings, so you really should trim before you insert into the database. That way you don't get all that crazy overhead everytime you want to select.
Let me describe the problem based on the example below.
Lets say there is a string "abc12345" (could be any!!!) and there is a table mytable with a column mycolumn of varchar(100).
There are some rows that ends with the last character 5.
There are some rows that ends with the last characters 45.
There are some rows that ends with the last characters 345
There are no rows that ends with the last characters 2345.
In this case these rows should be selected:
SELECT * FROM mytable WHERE mycolumn LIKE "%345"
That's because "345" is the longest right substring of "abc12345" that occurs at least once as the right substring of at least one string in the mycolumn column.
Any ideas how to write it in one query?
Thank you.
This is a brute force method:
select t.*
from (select t.*,
dense_rank() over (order by (case when mycolumn like '%abc12345' then 1
when mycolumn like '%bc12345' then 2
when mycolumn like '%c12345' then 3
when mycolumn like '%12345' then 4
when mycolumn like '%2345' then 5
when mycolumn like '%345' then 6
when mycolumn like '%45' then 7
when mycolumn like '%5' then 8
end)
) as seqnum
where mycolumn like '%5' -- ensure at least one match
from t
) t
where seqnum = 1;
This then inspires something like this:
select t.*
from (select t.*, max(i) over () as maxi
from t join
(select str, generate_series(1, length(str)) as i
from (select 'abc12345' as str) s
) s
on left(t.mycolumn, i) = left(str, i)
) t
where i = maxi;
Interesting puzzle :)
The hardest problem here is finding what is the length of the target suffix matching your suffix pattern.
In MySQL you probably need to use either generating series or a UDF. Others proposed these already.
In PostgreSQL and other systems that provide regexp-based substring, you can use the following trick:
select v,
reverse(
substring(
reverse(v) || '#' || reverse('abcdefg')
from '^(.*).*#\1.*'
)) res
from table;
What it does is:
constructs a single string combining your string and suffix. Note, we reverse them.
we put # in between the strings that's important, you need a character that doesn't exist in your string.
we extract a match from a regular expression, using substring, such that
it starts at the beginning of the string ^
matches any number of characters (.*)
can have some remaining characters .*
now we find #
now, we want the same string we matched with (.*) to be present right after #. So we use \1
and there can be some tail characters .*
we reverse the extracted string
Once you have the longest suffix, finding maximum length, and then finding all strings having the suffix of that length is trivial.
Here's a SQLFiddle using PostgreSQL:
If you cannot restructure the table I would approach the problem this way:
Write an aggregate UDF LONGEST_SUFFIX_MATCH(col, str) in C (see an example in sql/udf_example.c in the MySQL source, search for avgcost)
SELECT #longest_match:=LONGEST_SUFFIX_MATCH(mycol, "abcd12345") FROM mytbl; SELECT * FROM mytbl WHERE mycol LIKE CONCAT('%', SUBSTR("abcd12345", -#longest_match))
If you could restructure the table, I do not have a complete solution yet, but the first thing I would add a special column mycol_rev obtained by reversing the string (via REVERSE() function) and create a key on it, then use that key for lookups. Will post a full solution when I have a moment.
Update:
If you can add a reversed column with a key on it:
use the query in the format of `SELECT myrevcol FROM mytbl WHERE myrevcol LIKE CONCAT(SUBSTR(REVERSE('$search_string'), $n),'%') LIMIT 1 performing a binary search with respect to $n over the range from 1 to the length of $search_string to find the largest value of $n for which the query returns a row
SELECT * FROM mytbl WHERE myrevcol LIKE CONCAT(SUBSTR(REVERSE('$search_string'), $found_n),'%')
This solution should be very fast as long as you do not have too many rows coming back. We will have a total of O(log(L)) queries where L is the length of the search string each of those being a B-tree search with the read of just one row followed by another B-tree search with the index read of only the needed rows.
keyword = house
SELECT * FROM products WHERE description LIKE '%house%'
This query also returns records having keyword, for example, courthouse, but I want to look for house only. How do I search anywhere in the description for "house" only?
Thanks.
UPDATE
just for more clarification ..
actually house, can be at
- the start of the description .. "House for sale..",
- can be quoted -- "house", 'house'
- can have exclamation .. house!!!, house!
- others - house? etc ..
this is why I used %house%
Are you looking for longs strings containing the whole word?
Search for "whole word match" in MySQL
SELECT * FROM products WHERE description rlike '[[:<:]]house[[:>:]]'
rlike is synonim for REGEXP.
[[:<:]] denotes the start of the word and the
[[:>:]] end of the word.
It works for all your requirements (case insensitive, with quoted words or words ending, or begging, with exclamation points and other non-letter characters)
The % before and after will search any matching text before and after the search keyword, try this instead for exact search:
SELECT * FROM products WHERE description = 'house'
Simple thing only house means, use this
SELECT * FROM products WHERE description = 'house'
If you want any word contain house in backside means use this,
SELECT * FROM products WHERE description LIKE '%house'
If you want any word contain house in frontside means use this,
SELECT * FROM products WHERE description LIKE 'house%'
If you want any word contain house in anywhere in description means use this,
SELECT * FROM products WHERE description LIKE '%house%'
Try a space around the keyword:
SELECT * FROM products WHERE description LIKE '% house %' OR description LIKE 'house %' OR description LIKE '% house' OR description LIKE '% house%'
Edit: added more options in search. The last one would allow for house. or house,, though something like housecat would also match. Regex would work best here. This solution came from Astandar, who deleted his answer.
I have the most simple SQL
SELECT * FROM words
It has 13000 words (varchar). I need to get the longest word first in my output. I guess it might be possible with the WHERE command?
Alternative
If it doesn't work like that, is there a smart way to sort my output array so it will order it by the longest word first (in the 'word'-column). It looks like this (in the output loop)?
$output_array[$row['word']] = $row['another_word'];
Ordering the words by its length should do it:
SELECT *
FROM words
ORDER BY LENGTH(word) DESC
select * from words order by len(my_field) desc;