why isn't this returning random stuff? - mysql

EDIT AGAIN: someone posted the solution, but it has a wierd x I don't understand why the x is there but now it works!! SOMEBODY EXPLAIN !!!
EDIT: I NEED THE LAST 12 RECORDS IN TIME, I USE ID INSTEAD OF TIME BECAUSE THE LATER ONES IN TIME ALSO HAVE A BIGGER ID, I GUESS THAT DOESN"T WORK BECAUSE OF THE PRIMARY KEY THING??
here is a mysql statement
"SELECT * FROM items WHERE item_section='$section'
ORDER BY item_id DESC, rand() LIMIT 12"
I need to add the DESC because I want the most recently posted item corresponding to a larger ID number. What I want is the last 12 records, but for those 12 to be in random order. This isn't working, what gives? I think I am just getting the latest 12 records NON-randomized.

If you turn what you said into sql, you get the answer:
SELECT * FROM (
SELECT * FROM items
WHERE item_section = '$section'
ORDER BY item_id DESC
LIMIT 12) x
ORDER BY rand()
You first select the most recent 12 records (aliased as x here), then you order them randomly... that takes two queries: one nested inside the other.

Because your item_id is probably a primary key and thus the order is fully determined and rand() is a noop.
EDIT: since you probably don't care about the answer "why", what you want to do is remove item_id DESC, part:
SELECT * FROM items WHERE item_section='$section'
ORDER BY rand() LIMIT 12
and if you want that sorted by id
SELECT * FROM (SELECT * FROM items WHERE item_section='$section'
ORDER BY rand() LIMIT 12) AS q ORDER BY item_id;
and if you want randomized first 12
SELECT * FROM (SELECT * FROM items WHERE item_section='$section'
ORDER BY item_id DESC LIMIT 12) AS q ORDER BY rand();

Related

Order by views limiting, then order by another column

I have a query that selects * from my database ordering by views and limiting by 4:
SELECT * FROM articles WHERE visible = 1 ORDER BY views LIMIT 4;
But in the same query I want to find all other rows ordering by column updated_at.
I haved tryied things like this, but doesn't works:
(SELECT * FROM articles ORDER BY views DESC LIMIT 4)
UNION
(SELECT * FROM articles ORDER BY updated_at DESC);
The propose this are "pinning" the 4 hotest articles on home page and then ordering by time was updated.
Have any way to ORDER BY multiple ways in the same query without repeat the rows?
How can I do this?
Continuing with your current thinking, we can take a union of two subqueries. The first subquery is what you already included in your question, and finds the 4 more frequently viewed articles. The second subquery finds everything else. The trick here is to include in each subquery a computed field which we can use to keep track of the top 4 records from everything else. Then, we order by this computed field first, followed second by the updated_at field.
(
SELECT a.*, 1 AS label
FROM articles a
WHERE visible = 1
ORDER BY views DESC
LIMIT 4
)
UNION ALL
(
SELECT a.*, 2
FROM articles a
WHERE visible = 1
ORDER BY views DESC
LIMIT 1000000 OFFSET 4 -- the limit 1000000 is arbitrary; just use a number
) -- larger than the expected size of your table
ORDER BY
label, views, updated_at
From MySQL documentation:
... The default behavior for UNION is that duplicate rows are removed from the result. ...
And
... If ORDER BY appears without LIMIT in a SELECT, it is optimized away because it will have no effect anyway. ...
So the trick here is to use limit in the second query (it is up to you to choose the limit):
(SELECT * FROM articles WHERE visible = 1 ORDER BY views DESC LIMIT 4)
UNION
(SELECT * FROM articles WHERE visible = 1 ORDER BY updated_at DESC LIMIT 100);
The query was tested in MySQL 5.6 and 5.7.
You can use a comma to separate multiple ORDERcommands.
MySQL will order from left to right.
SELECT * FROM articles WHERE visible = 1 ORDER BY views, updated_at DESC LIMIT 4;

MYSQL LIMIT only the values where "viewed"=1 , but not viewed="0"

This is a tough one for me. I have a table that holds user notifications. There is a column "VIEWED" where 0 means it has NOT been viewed, 1 means it has.
I want to generate my list of notifications, SELECT * that is unviewed (0), however in the case that I have no un viewed notification, I don't want to just display "no notififications" I want to display a few old ones.
I'm already showing my most recent unviewed first. Is there a way to do something that shows ALL unviewed, but only a few viewed? Like below?
$QUERY= "SELECT * FROM point_member_notifications WHERE account_id='$accountid' ORDER BY viewed ASC, created_date DESC (LIMIT 10 WHERE VIEWED='1') "
Maybe you want UNION ALL, to limit the 'VIEWED' old ones, just place the limit clause inside the parentheses that enclose the SELECT
(SELECT * FROM point_member_notifications WHERE account_id='$accountid' ORDER BY viewed ASC)
UNION ALL
(SELECT * FROM point_member_notifications WHERE account_id='$accountid' WHERE VIEWED='1' created_date DESC LIMIT 10);
You could use a combination of LIMIT and UNION (or UNION ALL if you don't want to remove duplicate records). That could look like:
(SELECT *
FROM point_member_notifications WHERE account_id='$accountid' AND VIEWED='1'
ORDER BY created_date DESC LIMIT 10)
UNION ALL
SELECT *
FROM point_member_notifications WHERE account_id='$accountid' AND VIEWED='0'
ORDER BY created_date DESC
LIMIT 10
If you want to have 10 records unviewed + the 10 old records you need to put the 2nd SELECT in brackets too, otherwise the LIMIT 10 at the end will limit the whole thing. An ORDER BY viewed should not be necessary since UNION already selects the unviewed first and then the others.

MySQL - Getting Top n records and ordering by a specific column with pagination

I have got a problem with getting top n records from database and ordering them by a specific column and paginating them.
For example I want first 100 movies from movie table and order these first 100 records by name and display 10 records per page.
However this doesn't work;
SELECT name FROM movies ORDER BY id DESC, name DESC, LIMIT 0,10
I am quite confused here. In order to paginate I have to use LIMIT in such ways;
LIMIT 0,10 = FIRST PAGE
LIMIT 10,20 = SECOND PAGE
and so on.
In order to get first records, I use ORDER BY id DESC however when I want to list FROM Z to A, ORDER BY id DESC, name DESC doesn't do the trick.
In another words what I want to do is to get first (latest) 100 records out of 10.000 and order this 100 records by name (ASC or DESC) and / or by view (ASC or DESC).
I hope I was clear enough to explain my problem.
I will be glad if you could help me out with this one.
Shift the order of your order by statements
(updated)
select name
from ( select *
from movies
order by id desc
limit 100 )
order by name desc
limit 0,10
It uses the first one first and if equal it looks at the next one
You could try to use
select name from
(select name from movies order by id desc limit 0,100)
order by name desc limit 0,10
Wrap your select in another select;
SELECT name FROM (SELECT * FROM movies ORDER BY id DESC LIMIT 0,100) ORDER BY name DESC LIMIT 0,10
Edit: Updated limits.

Possible to select last 100 records in MySQL, then select random 10 from those results in one query?

I need to display 10 related videos on a video page that come from the same category as that video. The problem is that there could possibly be hundreds of thousands of rows for each category so running RAND() is out of the question and I would prefer not to create a myisam table that matches my innodb table and then full text search for related.
I am not sure if my idea is possible, but I would like to select 100 of the latest rows for that category ordered by date, and then select only 10 from that set randomly.
Is this possible and could you point me in the right direction please?
I'm assuming you have a simple table with an identity named ID, and you can do something like:
SELECT *
FROM (
SELECT ID, Name, VideoFile
FROM VideoTable
ORDER BY ID DESC
LIMIT 100
) Derived
ORDER BY RAND()
LIMIT 10
select * from
(select * from table ORDER BY DESC LIMIT 100)
ORDER BY rand()
LIMIT 10

Mysql - return last 3 results in table

i was wondering if there was an easy way with just an sql statement to return the last three results in the table but in that order i.e. if there are a hundered results it would return in the order of 98, 99, 100 not simply ordering by id DESC and limit 3 which would return in order 100, 99, 98
Any help much appreciated.
p.s. in this instance, lets say I don't know the amount of results and don't really want to send 2 sql requests just to find the amount ( for any OFFSET answers ).
One way would be to use DESC and then just sort them again:
SELECT * FROM (SELECT * FROM some_table ORDER BY id DESC LIMIT 3) a ORDER BY id
Two options, I guess.
You could use DESC to return them in reverse order as you stated, and just reverse the order again in your application code. This is potentially the most efficient, as you can do it in a single query and it can potentially only need to read three rows of an index.
You can first find out the number of results in the table, then do a LIMIT <results-3>, 3
Is it okay if you just flip it back to the original order?
SELECT * FROM (SELECT * FROM SOMETABLE ORDER BY ID DESC LIMIT 3) AS T ORDER BY ID;
Select *
FROM (SELECT * FROM yourTABLE ORDER BY ID DESC LIMIT 0,3) as TempTable ORDER BY ID