How to make MySQL result set the same as specified? - mysql

Select * from table where id in ($id_list)...
How to make the result the same order as specified in $id_list ?
If $id_list='2,1,5...' then the result set should be in the same order

Try FIND_IN_SET
SELECT * FROM tablename
WHERE id IN (1,5,10)
ORDER BY FIND_IN_SET(id, '1,5,10')

you need to order by with switch case
SELECT * FROM table
WHERE id IN (3,6,1,8,9)
ORDER BY CASE id WHEN 3 THEN 1
WHEN 6 THEN 2
WHEN 1 THEN 3
WHEN 8 THEN 4
WHEN 9 THEN 5
END
read more details on
MySQL ORDER problem

Use the FIELD() function.
SELECT *
FROM table
WHERE id IN ($id_list)
ORDER BY FIELD(id, $id_list)
Using FIELD() is better then using FIND_IN_SET(), Since they are compared as numbers.

Related

How to treat missing id 's value as 0 and order by it?

When I use in keyword in sql, there may be some id is missing , but I want treat them like they exist and other columns are null or 0.
For example, suppose I have a table with two columns and some rows:
[id,value1]
1      1
2      4
3      3
5      5
I may write sql like this:
select * from table where id in (1,4,5) order by value1 limit 0,2 ;
When this sql is executed, the return result is [(1,1),(5,5)].
But what I want is [(4,0),(1,1)], because I want to treat the missing id 4 like it exists in the table.
So the question is : Is there some elegant way to achieve it using sql instead of select all rows and sort them in memory.
Use a left join:
select *
from (select 1 as id union all
select 4 union all
select 5
) i left join
table t
using (id)
order by t.value1
limit 0, 2 ;
Note that you are ordering by a value in the existing table, so this depends on the fact that NULL is ordered before other values.

How to define a custom ORDER BY in MySQL query

I need output in following order(firstly, group by last 3 letters and then arrange in order based on the first 3 digits)
ColumnA
001_eng
004_eng
002_chn
003_usa
But order by ColumnA gives me
ColumnA
001_eng
002_chn
003_usa
004_eng
This is just sample data. I have hundreds of entries in this format and the values keep changing everyday. So, specifying all the entries inside the field is not a feasible option.
I'm not sure of how to use FIELD() in my case.
You can use FIELD:
select *
from tablename
order by
FIELD(ColumnA, '001_eng', '004_eng', '002_chn', '003_usa')
(please be careful if ColumnA is not in the list the field function will return 0 and the rows will be put on top)
or you can use CASE WHEN:
select *
from tablename
order by
case
when ColumnA='001_eng' then 1
when ColumnA='004_eng' then 2
when ColumnA='002_chn' then 3
when ColumnA='003_usa' then 4
else 5
end
or you can use a different languages table where you specify the order:
id | name | sortorder
1 | 001_eng | 1
2 | 002_chn | 3
3 | 003_usa | 4
4 | 004_eng | 2
then you can use a join
select t.*
from
tablename t inner join languages l
on t.lang_id = l.id
order by
l.sortorder
(with proper indexes this would be the better solution with optimal performances)
You can use SUBSTRING_INDEX in case all ColumnA values are formatted like in the sample data:
SELECT *
FROM mytable
ORDER BY FIELD(SUBSTRING_INDEX(ColumnA, '_', -1), 'eng', 'chn', 'usa'),
SUBSTRING_INDEX(ColumnA, '_', 1)
Demo here
you can use substring() and get order by
SELECT *
FROM table_name
ORDER BY SUBSTRING(ColumnA, -7, 3);

how to get the rows from mysql that is-5 or +5 then the current row?

I have a MySQL table. the column are ID, ChId, TotalView...
Suppose I want to get all the rows which have Totalview -5 then me to all +5 then me. I want to search in table for people who get similar views.
How I can write a query to get the all rows.
select * from test where test.chid = 1 and totalview are (-5 then current , +5 then current)
You may try this query
SELECT * FROM test WHERE totalview> (current-5) AND totalview< (current+5);
select * from test where test.chid = 1 and totalview>=(current-5) AND totalview<=(current+5)
use your current totalview in current
select * from test
where test.chid = 1
ORDER BY totalview ASC
LIMIT current-5, current+5
You should calculate "current-5" and "current+5"
Use the query:
SELECT totalview as current_view FROM test WHERE chid = 1
Then substitute current_view from above query:
SELECT * FROM test WHERE totalview BETWEEN current_view - 5 AND current_view + 5
Assume this query chid=1 returns 1 record.
If we're doing this all inside of MySQL, we can create a temporary variable called #current, and then query on the result.
SELECT #current := totalview FROM test WHERE chid = 1;
SELECT id, chid, totalview FROM test WHERE totalview BETWEEN #current - 5 AND #current + 5;
get your currentview in a subquery and use it in the search criteria
SELECT * FROM test, (SELECT totalview AS currentview FROM test WHERE child =1) t1
WHERE (totalview <= ( currentview +5 )

MySql: Fetch LIMITED results using GROUP BY clause on one table/view

I have a view 'view_type' like:
type------name------fid
type_a----name1-----12
type_a----name2-----27
type_a----name3-----45
type_a----name4-----43
type_a----name5-----25
type_a----name7-----75
type_a----name6-----15
type_b----bame1-----12
type_b----bame2-----27
type_b----bame3-----45
type_b----bame4-----43
type_b----bame5-----25
type_c----came7-----55
type_c----came6-----25
Now i want to fetch results having 'ame' in name field, but only from 'type_a' & 'type_b' and also only 4results from each.
type------name------fid
type_a----name1-----12
type_a----name2-----27
type_a----name3-----45
type_a----name4-----43
type_b----bame1-----12
type_b----bame2-----27
type_b----bame3-----45
type_b----bame4-----43
In simple words I want to limit results of 'group by' result set.
Don't want to use 'complex sub query' OR 'stored procedure'. Is there any simple query which help me out?
Try this query
select * from view_type where type = 'type_a' and name regexp 'ame' LIMIT 4
UNION
select * from view_type where type = 'type_b' and name regexp 'ame' LIMIT 4

mysql select update

Got this:
Table a
ID RelatedBs
1 NULL
2 NULL
Table b
AID ID
1 1
1 2
1 3
2 4
2 5
2 6
Need Table a to have a comma separated list as given in table b. And then table b will become obsolete:
Table a
ID RelatedBs
1 1,2,3
2 4,5,6
This does not rund through all records, but just ad one 'b' to 'table a'
UPDATE a, b
SET relatedbs = CONCAT(relatedbs,',',b.id)
WHERE a.id = b.aid
UPDATE: Thanks, 3 correct answers (marked oldest as answer)! GROUP_CONCAT is the one to use. No need to insert commas between the ids using relatedids = CONCAT(relatedids,',',next_id) that is done automatic by GROUP_CONCAT.
You'll have to use the mysql group_concat function in order to achieve this: http://dev.mysql.com/doc/refman/5.1/en/group-by-functions.html#function_group-concat
Look into GROUP_CONCAT(expr)
mysql> SELECT student_name,
-> GROUP_CONCAT(DISTINCT test_score
-> ORDER BY test_score DESC SEPARATOR " ")
-> FROM student
-> GROUP BY student_name;
You can't do that in standard SQL. You could write a stored procedure to do that. I had a similar problem, but I was using PostgreSQL so I was able to resolve it by writing a custom aggregate function so that you can do queries like
select aid, concat(id)
from b group by
aid
Update: MySQL has a group_concat aggregate function so you can do something like
SELECT id,GROUP_CONCAT(client_id) FROM services WHERE id = 3 GROUP BY id
as outlined here.