Fix for Issue #306 - DISTINCT + TOP + ORDER BY Associated Table #329
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixed selecting
DISTINCTrows from a table when ordering by a column that is not part of theSELECTlist where the join creates at least one extra row.While previously the test suite combined with Rails 4.0.0 looked like it worked, the constructed SQL would return incorrect values for
FinderTest#test_find_with_order_on_included_associations_with_construct_finder_sql_for_association_limiting_and_is_distinct. By using aGROUP BYandMAX()/MIN()in theORDER BYwith noDISTINCTcall, the order of the returned rows was not necessarily correct.With Rails 4.0.1, a related bug was fixed that introduces a new method,
columns_for_distinct. Unfortunately by adding the columns from theORDER BYclause to theSELECTlist, theDISTINCTnature of the queries was altered. This combined with a test limiting the results to only 2 records, exposed the bug.From testing various SQL constructs to solve the issue, I ended up determining that to properly return a single value from the related table used in the
ORDER BY, a query with a subquery utilizingROW_NUMBER()andDENSE_RANK()was needed. TheROW_NUMBER()was partitioned over the originally requested columns, and then the outer query would filter the results to just the first row of each partition.DENSE_RANK()was used to generate a proper ordering of the partitions in relationto each other.
In the process I also determined that extra code, plus an extra test, was necessary to ensure that when such a construct was generated using both a limit and offset, that the results would be correct also.
See #306 for further discussion, plus example queries and results.
These changes have been tested against Rails: