简体   繁体   中英

Order by using subselect and grouping

Here is a Fiddle: SQLFIDDLE

If you look in my subquery i select location ids and order them by the sort column . I want my final resultset to be ordered by the arrangement of my locids i selected in my subquery. So, for instance, it should have reviews for location 3166, then location 269, then location 3572 INSTEAD of it's current results .

Finally, I want to limit to one review per location (which means I want to order by the review createdate) which is why i used a group by locid.

So, for the final result set, I should get (in this order):

  • reviews row 16

  • reviews row 19

  • reviews row 24

This resultset fulfills the following requirements (in order):

  • Sorted by the sort flag in the locations table

  • Retrieved the most current review based on the sorted location

Thanks for the help. If you need any further information please dont hesitate to ask.

UPDATE

What I need is a list of reviews sorted by the location sort column and then the review create date with a limit of 1 per location. If you can solve this another way please let me know. Thanks

SECOND UPDATE

I've started trying using an inner join but i cannot get the record with the greatest createdate to display. SQLFIDDLE TWO

select * is entirely inappropriate when using group by . Aggregation queries should have aggregation functions.

The general answer to your question is to use join . A sample such query looks like:

select r.locid, count(*), max(r.createdate)
from reviews r join
     locations l
     on r.locid = l.locid
group by locid
order by sort;

!Edit: After getting clarity about what the sort column was for.... This should be what you're looking for: sqlfiddle.com/#!9/fa15b/9

 SELECT r.reviewid, r.locid, r.title, r.createdate, l.sort
 FROM reviews r
 INNER JOIN locations l ON l.locid = r.locid
 WHERE r.reviewid IN
     (SELECT MAX(r2.reviewid) FROM reviews r2
      GROUP BY r2.locid)
 ORDER BY l.sort

Explanation; I'm going to try to explain this as thoroughly as possible, so that if anyone else comes across this, it makes sense.

Lets start with what we "need" from this query:

  • all locations that have reviews
  • for the items to be sorted by "sort", from the locations table
  • the top (meaning most recent) review (from the reviews table) for each location

We'll tackle them one at a time:

  1. Joining locations that have reviews is as simple as it sounds. We run an SQL JOIN between reviews and locations on the key "locid", giving us a result set of only locations that have reviews (and vice versa)

  2. The next easiest thing to do is sort by your "sort" column. Hence the "ORDER BY l.sort". That leaves us with a full list of all reviews/locations mappings.

  3. The last item is to pick out only the most recent review for each location. Since the reviewid's are number in ascending order, The result of picking out the date vs the review id is the same and the reviewid is easier to me.

    • This is where the sub-query comes in; I want to get just a list of the most recent reviewid's (read: the primary key with the highest value) for each location.
    • I select the MAX(r2.reviewid) using a different alias from reviews so that I can compare it against the original list (r1). Note that if I left the MAX() here without the grouping, I would only get the highest reviewid out of all the reviews (6, I think in the example?)
    • Nearly finished, we group the subquery by r2.locid in order to return, for each separate locid, the highest numbered reviewid.
  4. The final piece of this puzzle is to reference the reviewid's from the subquery so that we only get the max id's we want; then type in whichever columns you want in the SELECT statement.

Additional notes:

  • We do not want locations without reviews
  • We do not want multiples of any location
  • I could also do a self join, using the same logic instead of the subquery, but I figured the WHERE clause was easier to understand.
  • If you, for some reason wanted locations that don't have any reviews to be included, you would need to use some weird RIGHT JOIN logic.
  • You should implement the previous two items, as an exercise.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM