I use the following MySQL query to get results, sorted alphabetically by name:
SELECT * FROM `client` WHERE CONCAT(name, ', ', firstname) LIKE "%ti%" ORDER BY name
In some way the results get sorted, so the ORDER BY works. Unfortunately it works not as expected. The above query gives the following order for example:
Kostic (31)
Hatscher (30)
Why is Kostic listed first? Prove me wrong, but K comes after H in the alphabet... (If it helps - the name field is type of varchar.)
It shouldn't be possible for K to come before H with ORDER BY name. Maybe a blank or even some unprintable character in front?
Test:
Do you get 'Kostic (31)' when you add AND name like 'K%'?
Do you get 'Hatscher (30)' when you add AND name like 'H%' instead?
I know ASC is the default when not specified in the ORDER BY but have you tried putting ASC after.. ORDER BY Name ASC. It's worth a shot
Related
I want SQL to show / order the results for the column name first then show results for the description column last.
Current SQL query:
SELECT * FROM products WHERE (name LIKE '%$search_query%' OR description LIKE '%$search_query%')
I tried adding order by name, description [ASC|DESC] on the end but that didn't work.
It's for optimizing the search results. If a certain word is found in description it should go last if a certain word is also found in the name column.
You can use a CASE statement in an ORDER BY to prioritize name. In the example below all results where name is matched will come first because the CASE statement will evaluate to 1 whereas all other results will evaluate to 2.
I'm not sure by your problem description what exactly you want the behavior to be, but you can certainly use this technique to create more refined cases to prioritize your results.
SELECT *
FROM products
WHERE (name LIKE '%$search_query%' OR description LIKE '%$search_query%')
ORDER BY CASE WHEN name LIKE '%$search_query%' THEN 1 ELSE 2 END
If you want the names first, the simplest order by is:
order by (name like '%$search_query%') desc
MySQL treats booleans as numbers in a numeric context, with "1" for true and "0" for false.
While this is undocumented, when results sets combined by a UNION ALL and not sorted afterwards, they stay in the order returned, as UNION ALL just adds new results to the bottom of the result set. This should work for you:
SELECT * FROM products
WHERE name LIKE '%$search_query%'
UNION ALL
SELECT * FROM products
WHERE (description LIKE '%$search_query%' AND name NOT LIKE '%$search_query%')
I have a very big table with strings.
Field "words":
- dog
- champion
- cat
- this is a cat
- pool
- champ
- boots
...
In my example, if a select query is looking for the given string "championship", it won't find it because this string is not in the table.
In that case, I want the query to return "champion" from the table, i.e. the longest string in the table that begins the given word "championship".
The possible match (if found) is the longest one in table between championship, or championshi, or championsh, or champions, ..., or cham, or cha, or ch, or C.
Question: I want to return longest string in table that starts a given string.
I need high speed. Is there a way to create index and query in order to have fast execution of queries?
Here's one query that will return the specified result:
SELECT t.mycol
FROM mytable t
WHERE 'championship' LIKE CONCAT(t.mycol,'%')
ORDER
BY LENGTH(t.mycol) DESC
LIMIT 1
This query can't do a index range scan, it's going to have to be full scan, but it may be able to use an index to satisfy the query.
If you can restrict the search to a finite number of leading letters that need to match to be considered a "hit", you could include another predicate. For example, to match at least 4 characters:
SELECT t.mycol
FROM mytable t
WHERE 'championship' LIKE CONCAT(t.mycol,'%')
AND t.mycol LIKE 'cham%'
ORDER
BY LENGTH(t.mycol) DESC
LIMIT 1
--or--
AND t.mycol >= 'cham'
AND t.mycol < 'chan'
You are a little vague with 'the longest string in the table that begins the given word "championship".' Would "championing" count as a match?
Perhaps the following will help. If you have an index on words, then the following will return the last word before the given word. It should maximize the initial sequence of matches:
select word
from t
where words <= 'championship'
order by words desc
limit 1;
This isn't exactly what you are asking for, but it might work in practice.
EDIT:
If you are looking for an exact match, then the following should use an index on words effectively and return what you want:
select word
from t
where word in ('championship', 'championshi', 'championsh', 'champions', 'champion',
'champio', 'champi', 'champ', 'cham', 'cha', 'ch', 'c')
order by word desc
limit 1;
It is a bit brute force, but it should have the property of using the index to speed up the query.
Have a look at this article:
http://blog.fatalmind.com/2010/09/29/finding-the-best-match-with-a-top-n-query/
It explains the solution from this SO question:
How to use index efficienty in mysql query
The solution pattern looks like this:
select words
from (
select words
from yourtable
where words <= 'championship'
order by words desc
limit 1
) tmp
where 'championship' like concat (words, '%')
I have a table like:
id name
--------
1 clark_009
2 clark_012
3 johny_002
4 johny_010
I need to get results in this order:
johny_002
clark_009
johny_010
clark_012
Do not ask me what I already tried, I have no idea how to do this.
This will do it, very simply selecting the right-most 3 characters and ordering by that value ascending.
SELECT *
FROM table_name
ORDER BY RIGHT(name, 3) ASC;
It should be added that as your data grows, this will become an inefficient solution. Eventually, you'll probably want to store the numeric appendix in a separate, indexed integer column, so that sorting will be optimally efficient.
you should try this.
SELECT * FROM Table order by SUBSTRING(name, -3);
good luck!
You may apply substring_index function to parse these values -
select * from table order by substring_index(name, '_', -1)
You can use MySQL SUBSTRING() function to sort by substring
Syntax : SUBSTRING(string,position,length)
Example : Sort by last 3 characters of a String
SELECT * FROM TableName ORDER BY SUBSTRING(FieldName, -3);
#OR
SELECT * FROM TableName ORDER BY SUBSTRING(FieldName, -3,3);
Example : Sort by first 3 characters of a String
SELECT * FROM TableName ORDER BY SUBSTRING(FieldName, 1,3);
Note : Positive Position/Index start from Left to Right and Negative Position/Index start from Right to Left of the String.
Here is the details about SUBSTRING() function.
If you want to order by the last three characters (from left to right) with variable name lengths, I propose this:
SELECT *
FROM TABLE
ORDER BY SUBSTRING (name, LEN(name)-2, 3)
The index starts at lenght of name -2 which is the third last character.
I'm a little late but just encountered the same problem and this helped me.
I'm trying to get a list of some products' model & all models are alphanumeric.
I tried
ORDER BY CAST(field_name AS UNSIGNED)
and
ORDER BY field_name + 0
and
ORDER BY LENGTH(field_name)
and some other ways.
They works for most of them but there are some values that doesn't match the order.
The result I get is like
EAG-75
EAG-110
...
ESCG-500
ESCG-600
...
EYG-40
EYG-55
...
EMG-440
EMG-20
EMG-27
...
EAG-100
...
I don't understand what is causing this.
Please help.
Thanks in advance
You need to sort the 2 bits separately if you want a correct numeric sort per non-numeric prefix
ORDER BY
-- sort by prefix only
LEFT(MyCol, INSTR(col, '-')-1),
-- sort numerically within prefix
CAST(SUBSTRING(MyCol, INSTR(col, '-')+1) AS UNSIGNED)
Would ORDER BY LENGTH(field_name), field_name work better for you?
I have a table call objects which there are the columns:
object_id,
name_english(vchar),
name_japanese(vchar),
name_french(vchar),
object_description
for each object.
When a user perform a search, they may enter either english, japanese or french... and my sql statement is:
SELECT
o.object_id,
o.name_english,
o.name_japanese,
o.name_french,
o.object_description
FROM
objects AS o
WHERE
o.name_english LIKE CONCAT('%',:search,'%') OR
o.name_japanese LIKE CONCAT('%',:search,'%') OR
o.name_french LIKE CONCAT('%',:search,'%')
ORDER BY
o.name_english, o.name_japanese, o.name_french ASC
And some of the entries are like:
Tin spoon,
Tin Foil,
Doctor Martin Shoes,
Martini glass,
Cutting board,
Ting Soda.
So, when the user search the word "Tin" it will return all results of these, but instead I just want to return the results which specific include the term "Tin" or displaying the result and rank them by relevance order. How can I achieve that?
Thanks.
You can use MySQL FULLTEXT indices to do that. This requires the MyISAM table type, an index on (name_english, name_japanese, name_french, object_description) or whatever fields you want to search on, and the appropriate use of the MATCH ... AGAINST operator on exactly that set of columns.
See the manual at http://dev.mysql.com/doc/refman/5.5/en/fulltext-search.html, and the examples on the following page http://dev.mysql.com/doc/refman/5.5/en/fulltext-natural-language.html
After running the query above , you will get all sort of results including ones that you are not interested, but you can then use regular expressions on the above results(returned by mysql server) set to filter out what u need.
This should do the trick - you may have to filter out duplicates, but the basic idea is obvious.
SELECT
`object`.`object_id`,
`object`.`name_english`,
`object`.`name_japanese`,
`object`.`name_french`,
`object`.`object_info`, 1 as ranking
FROM `objects` AS `object`
WHERE `object`.`name_english` LIKE CONCAT(:search,'%') OR `object`.`name_japanese` LIKE CONCAT(:search,'%') OR `object`.`name_french` LIKE CONCAT(:search,'%')
union
SELECT
`object`.`object_id`,
`object`.`name_english`,
`object`.`name_japanese`,
`object`.`name_french`,
`object`.`object_info`, 10 as ranking
FROM `objects` AS `object`
WHERE `object`.`name_english` LIKE CONCAT('%',:search,'%') OR `object`.`name_japanese` LIKE CONCAT('%',:search,'%') OR `object`.`name_french` LIKE CONCAT('%',:search,'%')
ORDER BY ranking, `object`.`name_english`, `object`.`name_japanese`, `object`.`name_french` ASC