select distinct values and order by the same column(value) - mysql

I have tried to find something to help me with this, but no luck.
I have a column "slide_no" with values 1-4.
I want to select everything from the database with distinct slide_no order by slide_no but show random selected images.
Database table
slide_id | slide_name | slide_no | fk_project_id
1 | pic1.jpg | 1 | 2
2 | pic2.jpg | 3 | 4
3 | pic3.jpg | 2 | 3
4 | pic4.jpg | 4 | 1
5 | pic5.jpg | 2 | 6
6 | pic6.jpg | 3 | 5
As you can see, the slide_no don't have to be unique, and I want it to be able to show random images on each page load. So far, I have only been able to produce a query that get the first 4 images out.
Is it possible to order by slide_no and get random images, with different (still ordered by slide_no) images?
Thanks in advance.

MySQL provides ORDER BY RAND() for this.
ORDER BY RAND() combined with LIMIT is useful for selecting a random sample from a set of rows.
The query will be:
SELECT *
FROM ( SELECT *
FROM `tblName`
GROUP BY slide_no
ORDER BY RAND()
) `tempTable`
ORDER BY slide_no ASC

You could try something like this if your just looking for a single random ID each time.
SELECT slide_id
FROM {table_name}
ORDER BY RAND()
LIMIT 1;

Working example:
http://www.sqlfiddle.com/#!2/0664c/8
Select slide_name, slide_no From
(SELECT *
FROM ( SELECT *
FROM tableName
GROUP BY slide_no, slide_name
ORDER BY RAND()
) `tempTable`
) x
Group by slide_no
ORDER BY slide_no ASC
limit 4

SELECT slide_no
, ( SELECT TOP 1 slide_name
FROM #tmp T2
WHERE T2.slide_no = T1.slide_no
ORDER BY RAND() --You can place other logic to "randomize" here in the future
)
FROM #tmp T1
GROUP BY slide_no;
I'm not sure if this gives you what you're looking for. The problem is that the repetitive calls of RAND() with the same seed value return the same results. If you want it to be truly random, that's another question in itself. See here for generating a random number in SQL.

Related

SELECT random but every name should be selected at least once

I have a problem in my MySQL query: I have more that 100000 records,
All I want is to select randomly 10 entries where I can see all devices at least once,
Devices names are differents from user to other.
The table has many devices name, the name is in another table where I joined to that table with the device ID
Every user has less than 10 devices so basically I can see all of them in LIMIT 10 but the random function doesn't pick some of them sometimes
I use :
SELECT DISTINCT name,signal
FROM my_table
Where name='any_name'
ORDER BY RAND()LIMIt 10
This selects 10 entries but sometimes some devices are not selected
Example :
+------------+------------+
| Device | Signal |
+------------+------------+
| Router1 | -60 |
| Router2 | -56 |
| Router3 | -102 |
| Router4 | -125 |
| ....... | .... |
+------------+------------+
Try using this code:
SELECT column_name FROM table_name ORDER BY RAND() LIMIT 10
But make sure you have put your column_name and table_name as your intended.
In additional, try to use this link beside:
http://jan.kneschke.de/projects/mysql/order-by-rand/
Good luck.
You can try this (untested). The logic is to select those device records that their signal is the maximum one for that device.
SELECT aa.name, aa.signal
FROM (
SELECT name, MAX(signal) AS max_signal
FROM my_table
GROUP BY name
) AS _aa
INNER JOIN my_table AS aa
ON aa.name = _aa.name
WHERE aa.signal = _aa.max_signal
ORDER BY RAND()
LIMIT 10;
Nasty way of doing it with a sub query on the SELECT:-
SELECT b.Device, (SELECT Signal FROM my_table a WHERE a.Device = b.Device ORDER BY RAND() LIMIT 1)
FROM
(
SELECT DISTINCT Device
FROM my_table
ORDER BY RAND()
LIMIT 10
) b

Return records from first record to get the number of records needed to return

Ok I really don't know how to explain this even in the title but this is what I want.
first I do have 5 records
id | name |
------------
1 | ringo |
------------
2 | nashi |
------------
3 | momo |
------------
4 | manga |
------------
5 | tokyo |
now I produce a random number on what row I will start querying. For example I got a random number of 4 and so I will get rows 4 and 5. But my problem is I need 4 records on every query. So it means I will go back to the first record and get the first two rows.
Is there any possible way that I can go back on the first row if my query results lacks the number of records I want?
This is a connected question Select from nth record and so on in MySQL that shows what I have done so far.
If you sort the table first by records greater than the pivot id, then by id, you need only LIMIT the resultset to the first four records:
SELECT * FROM my_table ORDER BY id >= 4 DESC, id LIMIT 4
See it on sqlfiddle.
Here's what I would do.
SELECT * FROM `your_table`
WHERE `id` >= 3 /* 3 is some random number */
UNION
SELECT * FROM `your_table`
WHERE `id` < 5
LIMIT 4
EDIT: eggyal's question in his comment is something worth considering. My suggestion with that option considered is below.
SELECT * FROM `your_table`
WHERE `id` >= 3 /* 3 is some random number */
UNION
SELECT * FROM (
SELECT * FROM `your_table` LIMIT 4
) a
LIMIT 4

Get user rank with MySQL

I read many topics about this problem but I can't find the solution.
I have a table (called users) with the users of my website. They have points. For example:
+-----------+------------+
| User_id | Points |
+-----------+------------+
| 1 | 12258 |
| 2 | 112 |
| 3 | 9678 |
| 4 | 689206 |
| 5 | 1868 |
+-----------+------------+
On the top of the page the variable $user_id is set. For example the user_id is 4. Now I would like to get the rank of the user by points (output should be 1 if the user_id is 4).
Thank you very much!
SELECT
COUNT(*) AS rank
FROM users
WHERE Points>=(SELECT Points FROM users WHERE User_id=4)
Updated with some more useful stuff:
SELECT
user_id,
points,
(SELECT COUNT(*)+1 FROM users WHERE Points>x.points) AS rank_upper,
(SELECT COUNT(*) FROM users WHERE Points>=x.points) AS rank_lower
FROM
`users` x
WHERE x.user_id = 4
which includes the range of ranks user is at. So for example if the scores for first five places are 5 4 3 3 3, the result would be:
id points rank_upper rank_lower
id 5 1 1
id 4 2 2
id 3 3 5
id 3 3 5
id 3 3 5
This query should do what you want :
SELECT rank FROM (
SELECT User_id, Points,
FIND_IN_SET(
Points,
(SELECT GROUP_CONCAT(
DISTINCT Points
ORDER BY Points DESC
)
FROM users)
) as rank
FROM users )
WHERE User_id = 4;
If you don't want to do it outside mysql you'll need to use variables to compute the rank.
Here's a solution that describes exactly what you want :
http://www.fromdual.ch/ranking-mysql-results
You still need, it you want to have it directly for each record, to store it in the record and to update it yourself. There is no reasonable query that will give you directly the rank without storage on a real table (I mean not just a few hundreds records).
There's already a simple solution, just suited for your purpose.
This may help
SELECT #rank:=#rank+1 AS rank,`User_id`,`Points` FROM `users` u JOIN (SELECT #rank:=0) r ORDER BY u.Points DESC

How to sort items in mysql based on data from another table?

I have the following tables:
word_list:
id | word
1 | ball
2 | car
3 | small
items_word_match:
itemid | wordid | in_title | in_description
1 | 1 | 1 | 0 //The word #1 occurs once in the title of the item
1 | 3 | 0 | 2 //The word #3 occurs twice in the title of the item
3 | 3 | 1 | 2
2 | 1 | 1 | 0
search:
wordid | importance
1 | 1
2 | 5
3 | 2 //word #3 is more important than the word #1 but less so than word #2
I want to sort the items based on the keywords from the search table and how important the keywords are.
And if the keyword is in the title the importance should increase by 1 and if the word appears 2 times the importance of the word should be importance*2
Neither of those answers from Denis or Johan are correct. Instead you could use this:
select
itemid,
sum(word_importance) as item_importance
from
(select
itemid,
search.wordid,
(
in_title * (importance + 1)
+ in_description * importance
) as word_importance
from
items_word_match,
search
where
i.wordid = s.wordid
)
group by itemid
As Johan pointed out, you need to add an order clause to the end, , order by item_importance desc
Feel a bit lazy today, so I'm just going to answer the question in the title:
How to sort items in mysql based on data from another table ?
You can sort the outcome of a query by any criterium you wish.
SELECT word_list.* FROM word_list
INNER JOIN search ON (search.wordid = wordlist.id)
ORDER BY search.importance, word_list.id DESC
Note that the JOIN needed to link the two tables together can have a profound effect on which rows in the word_list table are selected, but you need to do a JOIN somehow.
Otherwise MySQL will not know what the relationship between the two tables is and cannot sort the fields.
SELECT
i.itemid
, SUM( i.in_description * s.importance
+ i.in_title * ( s.importance + 1 )
)
AS item_importance
FROM
items_word_match i
LEFT JOIN
search s
ON s.wordid = i.wordid
GROUP BY
i.itemid
ORDER BY
item_importance DESC
CORRECTION:
I used LEFT JOIN catch the case when some words do not appear in the search table. But then the importance of those words seems appropriate to be 0 and not NULL, so the SUM should be changed into:
, SUM( i.in_description * COALESCE(s.importance, 0)
+ i.in_title * COALESCE(s.importance, 1)
)
your order by clause can contain fields from any of the tables:
select table1.*
from table1
join table2 using (table1_id)
order by table2.field, table1.field, etc.

select the first and the last two elements

hi i have a table with this elements
id name
1 luke
2 johnny
3 perry
4 jenny
5 mark
I have to do a query that take the first element and the lasts 2
i this example
1 luke
4 jenny
5 mark
how can i do?
thanks
I don't think you can do that with a single query : I'd say you'll have to use two queries :
One, to get the first result :
select *
from your_table
order by id asc
limit 1
And one other to get the two last results -- sorting in the opposite direction and getting the first two one will do the trick :
select *
from your_table
order by id desc
limit 2
After that, instead of doing two requests from your programming language to the SQL server, you could send only one query, that would use an UNION to get the results of both :
(select * from your_table order by id asc limit 1)
UNION
(select * from your_table order by id desc limit 2)
But, thinking about it... not sure this is actually possible, having a UNION with order by and limits in each sub-query...
EDIT : I did the test, and it's seems it's possible :
Here are the two queries, executed independantly :
mysql> select id, title from post order by id asc limit 1;
+----+--------------+
| id | title |
+----+--------------+
| 1 | Premier post |
+----+--------------+
1 row in set (0,00 sec)
mysql> select id, title from post order by id desc limit 2;
+----+-------------------------+
| id | title |
+----+-------------------------+
| 7 | Septième post |
| 6 | Sixième post (draft=7) |
+----+-------------------------+
2 rows in set (0,00 sec)
And here's what it looks like with the UNION :
mysql> (select id, title from post order by id asc limit 1) UNION (select id, title from post order by id desc limit 2);
+----+-------------------------+
| id | title |
+----+-------------------------+
| 1 | Premier post |
| 7 | Septième post |
| 6 | Sixième post (draft=7) |
+----+-------------------------+
3 rows in set (0,03 sec)
Note, though, that the order of the 3 resulting rows is not quite well defined...
And, quoting the following manual page of MySQL 5.1 : 12.2.8.3. UNION Syntax :
To apply ORDER BY or LIMIT to an
individual SELECT, place the clause
inside the parentheses that enclose
the SELECT:
(SELECT a FROM t1 WHERE a=10 AND B=1 ORDER BY a LIMIT 10)
UNION
(SELECT a FROM t2 WHERE a=11 AND B=2 ORDER BY a LIMIT 10);
However, use of ORDER BY for
individual SELECT statements implies
nothing about the order in which the
rows appear in the final result
because UNION by default produces an
unordered set of rows.
Take the union of Combine somehow (a) the top one, sorting ascending, (b) the top two, sorting descending.
In two queries:
select * from table order by id asc limit 1
select * from table order by id desc limit 2
I'm not sure if you can do it in 2 queries in mysql. You could do it this way in ms-sql:
select * from table order by id asc limit 1
union all
select * from table order by id desc limit 2
Well, it's not pretty to do it in one query (especially since MySQL doesn't support LIMIT in IN subqueries), but it's possible (but subqueries are kind of cheating):
SELECT id, name
FROM table
WHERE id = (SELECT id FROM table ORDER BY id LIMIT 1)
OR id = (SELECT id FROM table ORDER BY id DESC LIMIT 1)
OR id = (SELECT id FROM table ORDER BY id DESC LIMIT 1,1)