开发者

Retain ordering from IN subquery

开发者 https://www.devze.com 2023-04-10 16:20 出处:网络
this should be an easy one, but I can\'t seem to get mysql to play ball. I\'m trying to build a list of projects that a user most recently voted for, to be used on that users profile page.

this should be an easy one, but I can't seem to get mysql to play ball.

I'm trying to build a list of projects that a user most recently voted for, to be used on that users profile page.

I have table of votes, containing uid(INT), project(INT), timestamp(INT)

And a table of projects whose id field matches the project field in the votes table.

My initial query was

SELECT * FROM projects WHERE id IN(SELECT project FROM votes WHERE uid=x ORDER BY timestamp DESC);

This gives a correct list, but the ordering is messed up. I also realised that I had forgotten to add DISTINCT project to the subquery, but for some reason it was giving distinct projects anyway.

SELECT project FROM votes WHERE uid=x ORDER BY timestamp DESC;

On its own gives the correct ordering as expected, but as soon as I query from that, the ordering is discarded.

I must not understand how nested statements work, could someone help, and also explain why the DISTINCT keyword is not necessary to get distinct project ids from the votes table!?

An example as requested;

The votes table contains individual votes, so if a user votes for a project three times, it might look like this;

uid     project    timestamp
34      9          10984
34      9          11093
34      9          11309

If that user (34 in the example) then voted for a different project, the votes table would now look like;

uid     project    timestamp
34      9          10984
34      9          11093
34      9          11309
34      21         12612

The indicies 9 and 21 are then used to query the projects table. So for example the projects table might contain;

id     name           description
9      Proj开发者_Go百科ect A      This is project A.
21     Project B      This is project B.

What I want is the list of projects that the user most recently voted for. So in this case I want to grab projects 21 and 9 from the projects table in that order, 21 then 9 and on into projects that the user voted for further into the past.


I would use a join here instead of a subquery.

SELECT p.*
    FROM projects p
        INNER JOIN votes v
            ON p.id = v.project
    WHERE v.uid = x
    ORDER BY v.timestamp DESC;


try with ORDER BY FIELD - something like:

SELECT * FROM projects WHERE id IN(SELECT project FROM votes WHERE uid=x ORDER BY timestamp DESC) ORDER BY FIELD(id, (SELECT project FROM votes WHERE uid=x ORDER BY timestamp DESC) );


DISTINCT is not necessary because even though the IN() subquery may return duplicates, the outer query is merely looking for matching values among those, not 1:1 relationships. This is different than JOIN behavior, where you would likely end up with duplicate rows.

It's similar to saying you have an array [1,2,2,4,5,5] and asking which of the values from a different array [1,2,5,6] occur anywhere in the first array. The answer is always [1,2,5]. Hopefully this illustration isn't more confusing. I'll edit it as I think of ways to improve it.

Previous answers supply the correct ORDER BY.


You can rewrite this as a join:

SELECT DISTINCT projects.* FROM projects 
   JOIN votes ON projects.id = votes.project             
   ORDER BY timestamp DESC
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号