MySQL Rand() not in subquery? - php

I have a set of tracks that need to be played,
There are something like 70 tracks in the database, and my script need to generate a new ID to play in order to start the next track.
Current query: ($row['v_artist'] is the current artist playing)
SELECT *
FROM t_tracks
WHERE v_artist NOT LIKE '%".$row['v_artist']."%'
ORDER BY RAND()
LIMIT 1;
Now I wish to add a subquery to rand() so that it picks a random id, but not from the first 50 (NOT IN?)
Subquery:
SELECT *
FROM `t_playlist`
ORDER BY pl_last_played DESC
LIMIT 50, 1
How can I get a random ID from t_tracks that does not exist in the query for t_playlist?

Conceptually, I think you want this:
SELECT *
FROM t_tracks
WHERE v_artist NOT LIKE '%".$row['v_artist']."%' AND
track_id NOT IN (SELECT track_id FROM t_playlist ORDER BY pl_last_played DESC LIMIT 50)
ORDER BY RAND()
LIMIT 1;
However, MySQL doesn't permit LIMIT in some subqueries, so use LEFT JOIN instead:
SELECT t.*
FROM t_tracks t LEFT JOIN
(SELECT track_id
FROM t_playlist
ORDER BY pl_last_played DESC
LIMIT 50
) p
ON t.track_id = p.track_id
WHERE t.v_artist NOT LIKE '%".$row['v_artist']."%' AND
p.track_id IS NULL
ORDER BY RAND()
LIMIT 1;

Related

MySQL select grouping multiple rows from same table

I'm trying to create a query to select multiple rows from the same table grouping them like an array.
Now i'm selecting them using php like this:
$tks = mysqli_query($con,"SELECT * FROM hof ORDER BY tks DESC LIMIT 5");
$top_ths = mysqli_query($con,"SELECT * FROM hof ORDER BY ths DESC LIMIT 1");
$top_tha = mysqli_query($con,"SELECT * FROM hof ORDER BY tha DESC LIMIT 1");
----
I would like to merge them in a single query so i get an associative array.
Something like this:
(SELECT * FROM hol ORDER BY tks DESC LIMIT 5) AS tks
UNION
(SELECT * FROM hol ORDER BY ths DESC LIMIT 1) AS top_ths
So tks contains all the 5 rows and top_ths contains 1 row.
Is it possible ? Thanks.
to undersatnd from wich group row is, make additional field
(SELECT *, 1 as `group` FROM hol ORDER BY tks DESC LIMIT 5)
UNION
(SELECT *, 2 as `group` FROM hol ORDER BY ths DESC LIMIT 1)

Mysql - get last post from category

I have this structure (tables) of forum
I want to select last post (row from forum_post table) from category.
SQL so far:
SELECT * FROM table_post
WHERE topic_id = (SELECT MAX(id) FROM table_topic WHERE category_id = {$id})
ORDER BY id ASC LIMIT 1
Question: How to modify this select to achieve my goal?
Assuming that "last" means the biggest id, I would suggest order by and limit:
select fp.*
from forum_post fp join
forum_topic ft
on fp.topic_id = ft.id
where ft.category_id = $id
order by fp.id desc
limit 1;

Not In mysql subquery Limit

Does anybody have any ideas how I can get around a #1235 - This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery' error?
My query is below ( I've read that I can upgrade mysql but this isn't possible):
$query = #mysql_query("SELECT * FROM posts
WHERE postid NOT IN
( SELECT postid FROM log
ORDER BY posted DESC
LIMIT 10)
ORDER BY (RAND() * Multiplier)
LIMIT 1");
According to this bug, you can use this ugly workaround:
SELECT * FROM t1 WHERE s1 NOT IN
(SELECT * FROM (SELECT s2 FROM t2 ORDER BY s1 LIMIT 1) AS alias)
You can rewrite your query using JOIN:
SELECT *
FROM posts NATURAL LEFT JOIN (
SELECT postid FROM log ORDER BY posted DESC LIMIT 10
) t
WHERE t.postid IS NULL
ORDER BY RAND()
LIMIT 1
Be aware, however, that ORDER BY RAND() is very expensive. Not only must a random value be calculated for each record, but then a sort must be performed on the results. Indexes are of no use.
You would fare better if you had a column col containing unique integers, then with an index on col you can very rapidly obtain a random record with:
SELECT *
FROM posts NATURAL LEFT JOIN (
SELECT postid FROM log ORDER BY posted DESC LIMIT 10
) t JOIN (
SELECT RAND() * MAX(col) AS rand FROM posts
) r ON posts.col >= r.rand
WHERE t.postid IS NULL
LIMIT 1
Note that the uniformity of such "randomness" will depend on the distribution of the integers within col after any other filtering has taken place.

Different ORDER BY for each SELECT in a UNION with MySQL

Using PHP and MySQL, is there a way to use a different ORDER BY for each of the SELECT statements in a UNION?
SELECT * FROM the_table WHERE color = 'blue' ORDER BY price ASC LIMIT 5
UNION ALL
SELECT * FROM the_table WHERE color = 'red' ORDER BY RAND() LIMIT 10
The above statement does not work. It seems you can only do an ORDER BY on the final result set. Is there a way to do an ORDER BY on the first SELECT then a different ORDER BY on the second SELECT using UNION?
(SELECT * FROM the_table WHERE color = 'blue' ORDER BY price ASC LIMIT 5)
UNION ALL
(SELECT * FROM the_table WHERE color = 'red' ORDER BY RAND() LIMIT 10)
Please note that this does not work if you don't specify a LIMIT (though you can specify a very large dummy limit). See mysql documentation (13.2.7.3. UNION Syntax):
"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...
"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;
To additionally maintain sort order within individual SELECT results, add a secondary column to the ORDER BY clause:
"(SELECT 1 AS sort_col, col1a, col1b, ... FROM t1)
UNION
(SELECT 2, col2a, col2b, ... FROM t2) ORDER BY sort_col, col1a;"

Running a query with PHP/MySQL then reordering the results by another column

This SQL query gives me the results I want; however, I want the results ordered by a different column:
SELECT *
FROM post
INNER JOIN account ON post.account_id = account.account_id
WHERE post_id > new
ORDER BY post_date
ASC LIMIT 10;
I can not simply change ORDER BY post_date ASC to ORDER BY post_id DESC, while that will in fact order the query the way I want it... it will give me the wrong 10 posts.
I simply want to take the EXACT RESULTS of the above query then reorder the results by the post_id.
I would like to do this with SQL if possible, if not I could order the results by adding the results into a new array reversed.
Use a subquery to reorder:
SELECT * FROM (
SELECT *
FROM post
INNER JOIN account ON post.account_id = account.account_id
WHERE post_id > neww
ORDER BY post_date ASC LIMIT 10;
) ORDER BY post_id
Use a subquery:
SELECT * FROM (
SELECT *
FROM post
INNER JOIN account
ON post.account_id = account.account_id
WHERE post_id > neww
ORDER BY post_date ASC
LIMIT 10) AS T1
ORDER BY post_id DESC

Categories