SELECT *
FROM address
WHERE name LIKE 'a%' OR name LIKE '% a%' LIMIT 10
This query retrieves names that start with a either at the beginning 'a%'
or in a word in the middle '% a%'. How can I retrieve results from LIKE 'a%' first
then LIKE '% a%'?.
add ORDER BY clause,
SELECT *
FROM address
WHERE name LIKE 'a%' OR name LIKE '% a%'
ORDER BY CASE WHEN name LIKE 'a%' THEN 0 ELSE 1 END
LIMIT 10
Here it is:
SELECT t1.*
FROM (
SELECT *
FROM address
WHERE name LIKE 'a%'
LIMIT 10
) t1
WHERE t1.name LIKE '% a%'
A union query may be in order here. Per MySQL documentation
To cause rows in a UNION result to consist of the sets of rows retrieved by each SELECT one after the other, select an additional column in each SELECT to use as a sort column and add an ORDER BY following the last SELECT:
(SELECT 1 AS sort_col, col1a, col1b, ... FROM t1)
UNION
(SELECT 2, col2a, col2b, ... FROM t2) ORDER BY sort_col;
So for your case something like
(Select *, 1 as sortcol from addresses where name like 'a%')
Union
(Select *, 2 as sortcol from addresses where name like '% a%')
Order by sortcol
Link: http://dev.mysql.com/doc/refman/5.0/en/union.html
One approach is to add an ORDER BY clause to your query:
ORDER BY IF(name LIKE 'a%',1,2)
Something like this:
SELECT *
FROM address
WHERE name LIKE 'a%' OR name LIKE '% a%'
ORDER BY IF(name LIKE 'a%',1,2)
LIMIT 10
To avoid a "Using filesort" operation on large sets (i.e. LOTS of rows in address), and if you only want to return 10 rows, a more complex looking query will likely perform better, by limiting the number of rows to be sorted:
SELECT c.*
FROM ( SELECT a.*
FROM (
SELECT *
FROM address
WHERE name LIKE 'a%'
LIMIT 10
) a
UNION ALL
SELECT b.*
FROM address b
WHERE b.name LIKE '% a%' AND b.name NOT LIKE 'a%'
LIMIT 10
) c
ORDER BY c.name LIKE 'a%' DESC
LIMIT 10
Related
I want to select rows from tags table where tag name includes SOMETHING. The results must be sorted in a smart way: records which start with SOMETHING should go first, and then should go the rest.
It can be easily achieved using 2 queries: select by tag like 'SOMETHING%' first, and then by tag like '%SOMETHING%'. I want to combine this into one query. Is it possible? In general I want some equations which are usually used in WHERE clause to present in FIELDS section. For example,
SELECT
*,
(`name` like 'SOMETHING' ? 1 : 0) as weight0,
(`name` like 'SOMETHING%' ? 1 : 0) as weight1,
(match `name` against 'SOMETHING') as weight2,
length(name) as weight3
FROM `tags`
WHERE `name` like '%SOMETHING%'
ORDER BY weight0, weight1 desc, weight2 desc, weight3, name
LIMIT 0, 10
Obviously, the pseudo code above does not work, but I hope it shows the goal: moving WHERE conditions to SELECT area, assign numeric values, and the sort by these values. Is it somehow possible to achieve in MySQL?
You can use conditional statement like case when
SELECT
*,
(case when `name` like 'SOMETHING' then 1 else 0 end) as weight0,
(case when `name` like 'SOMETHING%' then 1 else 0 end) as weight1,
length(name) as weight3
FROM `tags`
WHERE `name` like '%SOMETHING%'
ORDER BY weight0, weight1 desc, weight3, name
LIMIT 0, 10
MySql evaluates boolean expressions as 1 for true or 0 for false and they can be used in the ORDER BY clause:
SELECT *
FROM tags
WHERE name LIKE '%SOMETHING%'
ORDER BY name = 'SOMETHING' DESC,
name LIKE 'SOMETHING%' DESC,
name LIKE '%SOMETHING%' DESC, -- this is not actually needed
CHAR_LENGTH(name),
name
LIMIT 0, 10;
how to write a single query for my scenario?
I have three where conditions ?
select * (select * ,'sony' as searchItem from dg_deal_product where name like '%sony%' or
select * , 'samsung' as searchItem from where dg_deal_product where name like '%samsung%' or
select * , 'wip' as searchItem from where dg_deal_product where name like '%wip%') order by column desc,column2 desc,column3;
Just guessing here, but perhaps you are looking for something like this:
SELECT p.*
,CASE WHEN p.name LIKE '%sony%' THEN 'sony'
WHEN p.name LIKE '%samsung%' THEN 'samsung'
WHEN p.name LIKE '%wip%' THEN 'wip'
ELSE NULL
END AS searchItem
FROM dg_deal_product p
ORDER BY 1 DESC, 2 DESC, 3
Let's consider a made up example
SELECT id, name, score.score FROM
someTable,
(select someTableId, count(*) as score FROM SecondTable GROUP BY someTableId) as score
WHERE score.someTableId == id
ORDER BY score.score DESC
Let's now assume that I have a backend computing my scoring, and that I would like to remove the subquery and insert my own data instead. I would like to know how to do this.
I would like to do something like (this is the question, because what's below doesn't work):
SELECT id, name, score.score FROM
someTable,
((12,324), (1, 342)) as score(id, score)
WHERE score.someTableId == id
ORDER BY score.score DESC
Here is an example of external data substitution to a subquery:
SELECT * FROM users WHERE id IN (SELECT user_id FROM posts WHERE thread_id = 12 GROUP BY user_id);
Without a subquery and with external data:
SELECT * FROM users WHERE id IN (1,2,3);
If I understood you correctly :
SELECT id, name, score.score FROM
someTable,
(SELECT 12 as someTableId,324 as score UNION ALL SELECT 1, 342 <UNION ALL....>) as score(id, score)
WHERE score.someTableId == id
ORDER BY score.score DESC
Thats the only way you can do it, it doesn't actually replace the the subquery, but it replace the select from the table and can improve performance if thats what you are looking for.
In MySQL you don't need to specify a from clause like a dummy table when you are just looking to fetch dummy data.
Other DBMS require a dummy table name (typically DUAL) but in MySQL it's rather straightforward:
SELECT 12 AS id, 324 AS score
UNION ALL SELECT 2, 65
UNION ALL SELECT 3, 598
UNION ALL SELECT 4, 244
You can use this as any other result-set.
select count(*) as total FROM ( SELECT * FROM database1.orders WHERE number LIKE "11111111111111111" UNION ALL SELECT * FROM database2.orders WHERE number LIKE "11111111111111111" ) AS b
but i got error :
The used SELECT statements have a different number of columns
because run SELECT * FROM database2.orders WHERE number LIKE "11111111111111111" give me a result is null.
How to merge it with a query because with a query to help me process the pagination
Thank for helps !
Just do the aggregation before the union all:
select sum(cnt) as total
FROM ((SELECT count(*) as cnt
FROM database1.orders
WHERE number LIKE '11111111111111111'
)
UNION ALL
(SELECT count(*) as cnt
FROM database2.orders
WHERE number LIKE '11111111111111111'
)
) t;
Note I changed the string delimiter to be a single quote rather than a double quote. It is good practice to use single quotes for string and date constants (and nothing else).
By the way, you can also do this using a join:
select o1.cnt1, o2.cnt1, (o1.cnt1 + o2.cnt1) as total
FROM (SELECT count(*) as cnt1
FROM database1.orders
WHERE number LIKE '11111111111111111'
) o1 cross join
(SELECT count(*) as cnt2
FROM database2.orders
WHERE number LIKE '11111111111111111'
) o2;
This makes it easier to get the individual counts for the two databases.
The orders table in database1 probably has a different number of columns than the table by the same name in database2.
Instead of using select *, select the columns you're interested in, like select userid, productid, deliveryaddress, .... Make sure you specify the same columns in both parts of the union.
For a count(*), you could choose no columns at all, and select the value 1 for each row, like:
select count(*)
from (
select 1
from database1.orders
where number like '111'
union all
select 1
from database2.orders
where number like '111'
) as SubQueryAlias
Or you can add the result of two subqueries without a union:
select (
select count(*)
from database1.orders
where number like '111'
)
+
(
select count(*)
from database2.orders
where number like '111'
)
Database entries
table test
name
========================
Sunae Kasimov
Obsop Natty
Preem Kuman
Mysql query
select *
from test
where name like 'na%' or
name like '% na%' or
name like '%na%';
return in order
1 and then 2
but i wanted in order 2 and 1. That is want to give more weight to '% na%' then '%na%'
Any way this can be done in mysql?
select * from
(
select * from name where name like '% na%'
union
select * from name where name like 'na%'
union
select * from name where name like '%na%'
) a
You should create virtual filed in your select and order by it. For example:
select test.*,
case when name like '% na%'
then 1
else 2
end as OrderField
from test
where name like 'na%' or
name like '% na%' or
name like '%na%'
order by OrderField