-
Notifications
You must be signed in to change notification settings - Fork 11.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[5.3] [WIP] Add relationship subqueries for avg, max, min and sum #16815
Conversation
hurray! |
BTW, maybe this should be generalized for all aggregations? |
Well... It makes sense to generalize If you want you can go ahead and make a suggestion how to implement it. |
Oh, yes, Suggestion is fairly simple: add extract current logic of public function withSum($relation, $column)
{
return $this->withAggregate('sum',$relation, $column);
}
public function withAvg($relation, $column)
{
return $this->withAggregate('avg',$relation, $column);
}
// etc |
You could actually create a method called Instead of passing We could pass an optional third parameter to define the resulting column name, then if you desire you can add those methods withSum, withAvg and call this method behind the scenes similar to what @terion-name proposed, the difference is that we would have another method that we could use... You could also generalize |
@makuser Thanks for your work. I hope it will be merged. |
* Implement new protected wrapper `withAggregate()` * Implement new public function `withRaw()` to allow DB::raw() usage e.g. for `sum(price - discount)` * Implement new subquery aggregates `withAvg()`, `withMax()`, `withMin()` and `withSum()` using `withAggregate()` wrapper * Generalize `withCount()` by using `withAggregate()` wrapper
Travis test failed, because I changed the column name suffix / alias behavior and did not yet adjust the test case, because I wanted to clarify this first:
|
Considering that this will change the behavior of withCount then it should probably target 5.4 (master), it should change btw, makes sense... 👍 |
Can you summarize the breaking changes of this? @fernandobandeira @makuser |
Sure thing. The breaking change would be, that I think it should rightfully be |
This doesn't work for me:
When I clone down the PR and try this with the correct tables in place and two transactions in the table I get "transactions_sum" as If I use withCount I get the correct count of |
Which amount value do your two transactions have? |
This makes me wonder how good these integration tests are? Or if they are even running? |
They are running, I had them check against Will investigate and fix. |
So, now it's fixed. Sorry for that, I had to undo 59c89a6 and 8b3e271, because this wasn't working as expected. I thought we always need to escape the column name with double quotes (SQL-99 standard, or SQLite keywords) but it seems like in reality we are not supposed to do that. Anyway, I now checked out the code again and tested it once against So what do you think @taylorotwell? |
I still don't think this is actually correct. The column should still be wrapped in the proper identifiers for the database driver. For example, for MySQL the ` character. |
*/ | ||
protected function withAggregate($aggregate, $relation, $column) | ||
{ | ||
return $this->withRaw($relation, new Expression($aggregate.'('.$column.')'), $aggregate); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
change this to
$this->query->grammar->wrap($column);
And call this directly for the withCount, * shouldn't be wrapped... that's what taylor is saying...
Tests should fail after you make this change, you'll have to update them accordingly to match the return...
Might be better to target 5.4? |
We need real integration tests. Simply comparing the compiled SQL is not an integration test. We should test this against models with proper relationships and test data, to ensure we actually get the results we expect. |
That is very true. Right now I simply took the tests that were already there for We definitely do need some REAL integration tests, also because the escaping/wrapping is obviously different per SQL engine. Anyone got an idea how to make some better integration tests? |
Closing this for now and maybe we can revisit on 5.4. |
@taylorotwell when will be the time to bring this in for 5.4.? It would actually be ready to merge with 5.3 right now. I fixed all of the code to actually work with the latest commits on upstream. I also adjusted all TestCases to work. These could be improved further, but they are also working as they are right now. |
@makuser are you using this in production now? |
I really liked
withCount()
, but I needed to sum a specific column of a relation, so I went ahead and implementedwithSum()
:Example:
Resulting query:
By using this function, you can easily
orderBy('transactions_sum', 'desc')
:You can also apply additional constraints like you can with the function
withCount()
, in this example to only sum-up the transactions of the last 21 days and only those with a specific item_id.Resulting query: