Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Distinct Records with joins and order

I have a simple relationship between User and Donations in that a user has many donations, and a donation belongs to a user. What I'd like to do is get a list of users, ordered by the most recent donations.

Here's what I'm trying:

First I want to get the total number of uniq users, which is working as expected:

> User.joins(:donations).order('donations.created_at').uniq.count
   (3.2ms)  SELECT DISTINCT COUNT(DISTINCT "users"."id") FROM "users" INNER JOIN "donations" ON "donations"."user_id" = "users"."id"
 => 384

Next, when I remove the count method, I get an error that "ORDER BY expressions must appear in select list":

> User.joins(:donations).order('donations.created_at').uniq
  User Load (0.9ms)  SELECT DISTINCT "users".* FROM "users" INNER JOIN "donations" ON "donations"."user_id" = "users"."id" ORDER BY donations.created_at
PG::InvalidColumnReference: ERROR:  for SELECT DISTINCT, ORDER BY expressions must appear in select list
LINE 1: ...ON "donations"."user_id" = "users"."id"  ORDER BY donations....

Then I tried fixing the Postgres error by explicitly setting the SELECT clause which at first glance appears to work:

 > User.select('DISTINCT "users".id, "users".*, "donations".created_at').joins(:donations).order('donations.created_at')
  User Load (17.6ms)  SELECT DISTINCT "users".id, "users".*, "donations".created_at FROM "users" INNER JOIN "donations" ON "donations"."user_id" = "users"."id" ORDER BY donations.created_at

However, the number of records returned does not take into account the DISTINCT statement and returns 692 records:

> _.size
 => 692

How do I get the expected number of results (384) while also sorting by the donation's created_at timestamp?

like image 678
Peter Brown Avatar asked Feb 23 '14 15:02

Peter Brown


People also ask

How do you SELECT distinct columns in join queries?

DISTINCT is for all the columns in the select clause, which means all columns combined will be used to get distinct rows. TOP X will only select the number of rows mentioned in X .

How to unique records in SQL?

The SQL SELECT DISTINCT Statement The SELECT DISTINCT statement is used to return only distinct (different) values. Inside a table, a column often contains many duplicate values; and sometimes you only want to list the different (distinct) values.

How use distinct keyword in join?

You can use CTE to get the distinct values of the second table, and then join that with the first table. You also need to get the distinct values based on LastName column. You do this with a Row_Number() partitioned by the LastName, and sorted by the FirstName.

How DISTINCT works in SQL?

The SQL DISTINCT keyword is used in conjunction with the SELECT statement to eliminate all the duplicate records and fetching only unique records. There may be a situation when you have multiple duplicate records in a table.


1 Answers

Try this:

User.select('users.*,MAX(donations.created_at) as most_recent_donation').
  joins(:donations).order('most_recent_donation desc').group('users.id')

I suppose an user has many donations, this would select the most recent created donation and would select distinct users filtering by their id.

I have not tested this though.

like image 85
sites Avatar answered Oct 17 '22 23:10

sites