Rails - Distinct ON after a join
Use a subquery and add a different ORDER BY
clause in the outer SELECT
:
SELECT *
FROM (
SELECT DISTINCT ON (pr.id)
pu.updated_at, pr.*
FROM Product pr
JOIN Purchases pu ON pu.product_id = pr.id -- guessing
ORDER BY pr.id, pu.updated_at DESC NULLS LAST
) sub
ORDER BY updated_at DESC NULLS LAST;
Details for DISTINCT ON
:
- Select first row in each GROUP BY group?
Or some other query technique:
- Optimize GROUP BY query to retrieve latest record per user
But if all you need from Purchases
is updated_at
, you can get this cheaper with a simple aggregate in a subquery before you join:
SELECT *
FROM Product pr
JOIN (
SELECT product_id, max(updated_at) AS updated_at
FROM Purchases
GROUP BY 1
) pu ON pu.product_id = pr.id -- guessing
ORDER BY pu.updated_at DESC NULLS LAST;
About NULLS LAST
:
- PostgreSQL sort by datetime asc, null first?
Or even simpler, but not as fast while retrieving all rows:
SELECT pr.*, max(updated_at) AS updated_at
FROM Product pr
JOIN Purchases pu ON pu.product_id = pr.id
GROUP BY pr.id -- must be primary key
ORDER BY 2 DESC NULLS LAST;
Product.id
needs to be defined as primary key for this to work. Details:
- PostgreSQL - GROUP BY clause
- Return a grouped list with occurrences using Rails and PostgreSQL
If you fetch only a small selection (with a WHERE
clause restricting to just one or a few pr.id
for instance), this will be faster.
Distinct Records with joins and order
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.
Get distinct rows using inner join
Event
.joins(:picks)
.where(picks: {result: nil, created_at: 5.days.ago..Time.now, league_id: 1})
.group("events.id")
Distinct Join Rails
Try using :include
instead of :joins
and you should not see any more duplicate video results.
Also, you should be using a lambda in your named_scope, otherwise Time.now
will be cached the first time you use it and you'll start getting incorrect results.
named_scope :scheduled_in_future, lambda {
{
:include => :events,
:conditions => ["event.scheduled_start > ? AND event.status = ?", Time.now.to_i, 'PENDING']
}
}
Rails: remove duplicates after ordering a join table
In
Book.joins(:reviews).order('reviews.created_at DESC').distinct
you're trying to select distinct bookings from the join table of books and reviews, and then order this list of distinct bookings according to the reviews.created_at
time. The SQL would be like this:
SELECT DISTINCT "books"."id" FROM "books" INNE JOIN "reviews" ON "reviews"."book_id" = "books"."id" ORDER BY reviews.created_at
There is a good reason why this is not allowed. Because the results are indeterminate. Imagine you have 100 reviews for one book. In the join table, you'll have 100 rows of this book with all different reviews. When you select a distinct list, you end up with one row of this book. This could be any one of the 100 in the join table. Then you order this based on the created_at
of this review. As the review could be any one of the 100, the order could be different every time.
This would be perfectly fine:
Book.joins(:reviews).order('books.id DESC').distinct
Because it doesn't matter which of the 100 rows it picks for that book, the books.id
is the same.
Back to your problem. Seems you're trying to get the 5 books with the most recent reviews. I don't see a simple way to do it but here's my solution:
res = Review.group("book_id").maximum("created_at") # {book_id => create_at}, each book with its most recent review time
arr = res.to_a.sort { |a,b| b[1]<=>a[1] } #array sorted by created_at in desc order
arr.map{ |n| n[0] }.take(5) #top 5 books' ids with most recent reviews
Ruby on Rails 4 count distinct with inner join
After doing long chat, we found the below query to work :
self.member
.engines(:reload)
.count("DISTINCT engine_code")
Returns distinct record in a joins query - Rails 4
First of all, I believe your model is "An Order
has many OrderStatusDetail
". So that is the reason why you have several different name
in your result.
So you can modify the query like this:
@orders = Order.joins(order_status_details: :order_status)
.order('id DESC, order_status_details.created_at DESC')
.where('order_status_details.id IN (SELECT MAX(id) FROM order_status_details GROUP BY order_id)')
.select("orders.id, order_status_details.status_id, order_statuses.name, order_status_details.created_at")
Ideally, the where
condition is used for selecting just the expected id of order_status_details
, I use min_id
for example, you can modify it as needed
Related Topics
Rodbc SQLquery() Returns Varchar(255) When It Should Return Varchar(Max)
Inner Join VS Multiple Table Names in "From"
Sql: Aggregating Strings Together
Oracle - Update Join - Non Key-Preserved Table
Limit Characters Returned in Oracle SQL Query
Sample Query to Show Cardinality Estimation Error in Postgresql
Relationship of Primary Key and Clustered Index
Pass in "Where" Parameters to Postgresql View
Work Around SQL Server Maximum Columns Limit 1024 and 8Kb Record Size
SQL Server 2008 Iif Statement Does Not Seem Enabled
How to Read Multiple Result Sets Returned from a SQL Server Stored Procedure in R
Count(Id) VS. Count(*) in MySQL
Subtract Hours from the Now() Function
SQL Sort Order with Null Values Last
Shredding Xml from Execution Plans
How to Give an Alias to a Table in Oracle
Add Primary Key to Existing Table
SQL Query for a Carriage Return in a String and Ultimately Removing Carriage Return