Complicated sorting of mysql result - mysql

I wonder if its possible to sort a result so that if a column contains a spesific word ('misc'), it will come out last?
current query:
select * from table order by name asc
current result:
banjo
guitar
miscproduct1
miscproduct2
piano
pseudocode:
select * from table order by name asc,
except if name like '%misc%' then sort it last
pseudo result:
banjo
guitar
piano
miscproduct1
miscproduct2
Is this possible?

You could use LOCATE() as the first ordering argument:
ORDER BY LOCATE('misc', name), name;
The LOCATE() function returns 0 if the search string can't be found in the subject, and yields a positive integer if it is found.
To normalize the sorting for subjects that contain the search you can combine with LEAST():
ORDER BY LEAST(LOCATE('misc', name), 1), name;

You can use a CASE in the ORDER BY clause.
SELECT colName
FROM table
ORDER BY
CASE WHEN colName LIKE 'misc%'
THEN concat('zzz',colName)
ELSE colName
END
Demo: http://sqlfiddle.com/#!2/6e08c/7

Related

SQL show results for A column first then show results for B column

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%')

Write a Select Statement to Query

I'm trying to query the first letter of a last name in MySQL. I want to skip the first name and query the a certain letter in the last name. Thanks
In SKU_data, which SKU has a buyer whose last name begins with 'M'?
*/
select *
from sku_data
where buyer ;
In your where clause, search on WHERE buyer.LastName LIKE 'M%'. This will return all results that start with M.
You need to use a combination of the substring method and the substring_index method in your sql query.
Your select query should look something like this
SELECT SUBSTRING(last_name,1,1)
I'm assuming that your name field has both first and last name in it, instead of separate fields for first and last name. Use the substring_index method to figure out what last_name should be:
SUBSTRING_INDEX(full_name,' ',-1)
Combining this SQL, we have:
SELECT SUBSTRING(SUBSTRING_INDEX(buyer,' ',-1),1,1) as first_letter
Now you can use the first_letter field in a where clause to get your desired result:
SELECT *, SUBSTRING(SUBSTRING_INDEX(buyer,' ',-1),1,1) as first_letter
from sku_data
where first_letter = 'M' ;
Assuming that you have a field like say "full_name" which has first name and last name in the same column.
Lets say the full_name in table employee has a value "JEFF MOSTI"
You can simply use the following statement to get what you need
select * from employee where full_name regexp ' M';
I am assuming you are looking for the last name to start with 'M' and that there is a space (' ') between the first and last name.

Best way to return "champion" that exists in a table in case the given query "championship" is not found

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, '%')

Order by last 3 chars

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.

ORDER BY word starts or inside field

I have an ajax-search on a mysql-db. Example: Search for "man" which I query with:
SELECT id FROM table WHERE name LIKE '%man%;
I now want to sort the result to have all results starting with the search in alphabetical order:
man
mankind
after that I want to have all results width the search INSIDE in alphabetical order, like:
iron man
woman
How can I do that?
You can order by the position of your search term in the string:
SELECT id
FROM table
WHERE name LIKE '%man%'
ORDER BY INSTR(name, 'man'), name
See also: INSTR(), LOCATE()
You could also change the expression to only distinguish between start of the string or anywhere else:
ORDER BY IF(INSTR(name, 'man'), 1, 0)
You can construct your ORDER BY using a CASE statement to verify the substrings. Note: I am using UPPER() here to convert both the search value and the column value to uppercase, for a case-insensitive match. If that is not your need, remove the UPPER().
ORDER BY
CASE
/* Matches the start of the string */
WHEN UPPER(LEFT(name, 3)) = 'MAN' THEN 1
/* Doesn't match the end or the start (in the middle) */
WHEN UPPER(RIGHT(name, 3)) <> 'MAN' THEN 2
/* Matches the end of the string */
WHEN UPPER(RIGHT(name, 3)) = 'MAN' THEN 3
ELSE 4
END,
/* Then order by the name column */
name
This method should be fairly portable, but I like the INSTR() answer below better.
Try this
SELECT id FROM table WHERE name LIKE 'man%';
UNION
SELECT id FROM table WHERE name LIKE '%man%';