-
Notifications
You must be signed in to change notification settings - Fork 28
[Proposal] Add whereNot() to the Query Builder #708
Comments
Do it up, buttercup. Submit that PR. 🥇 |
I don't understand the SQL statement 'select * from table where b=true and NOT (e != 1 and f < 5 and (g != null and h >= 150))'. How does whereNo() fit in when people can use "where('status', '<>', 1)" |
whereNot() would be usefull if the sub part is not allowed to return true, it would make queries like these a lot simpler as it is hard to turn it around so it will return false instead of true. |
I see. So whereNot will convert the result of the subquery from true to false and vice versa? |
No it will just add the not before the subquery brackets () which you currently can't do in eloquent |
Looking for this myself. Upvote. Would love to know where the short term workaround is. |
Acceptance just depends on how complicated it is to implement. |
By adding this operator we can negate a complex query in a expressive way. For example, the query pointed by @DrowningElysium: `select * from table where b=true and NOT (e != 1 and f < 5 and (g != null and h >= 150))` To be done currently in laravel query builder it's necessary to invert all operators (`and` to `or`, `!=` to `==`, `<` to `>=`, `>=` to `<`). If we need to do the negation dynamically we will need to maintain two querys, increasing the possibility of bugs. For example: ``` DB::table('table') ->where('b', true) ->when($invert, function ($query) { return $query ->where('e', '!=', 1) ->where('f', '<', 5) ->where(function ($query) { return $query->whereNotNull('g') ->where('h', '>=', 150); }); }, function ($query) { return $query ->where('e', '=', 1) ->orWhere('f', '>=', 5) ->orWhere(function ($query) { return $query->whereNull('g') ->orWhere('h', '<', 150); }); }); ``` With whereNot we can writte this query as: ``` $subquery = function ($query) { return $query ->where('e', '!=', 1) ->where('f', '<', 5) ->where(function ($query) { return $query->whereNotNull('g') ->where('h', '>=', 150); }); }; DB::table('table') ->where('b', true) ->when($invert, function ($query) use ($subquery) { return $query->whereNot($subquery); }, function ($query) use ($subquery) { return $query->where($subquery); }); # Or just: DB::table('table') ->where('b', true) ->{$invert ? 'where' : 'whereNot'}($subquery); ``` Which is more simple and legible to read. We only allow calling whereNot in callback form: $query->whereNot($callback); because allowing the use as column `whereNot($column)` can confuse the developer since the behaviour of not() in some fields, like varchar, is different from php !$string. Resolve laravel/ideas#708
By adding this operator we can negate a complex query in a expressive way. For example, the query pointed by @DrowningElysium: `select * from table where b=true and NOT (e != 1 and f < 5 and (g != null and h >= 150))` To be done currently in laravel query builder it's necessary to invert all operators (`and` to `or`, `!=` to `==`, `<` to `>=`, `>=` to `<`). If we need to do the negation dynamically we will need to maintain two querys, increasing the possibility of bugs. For example: ``` DB::table('table') ->where('b', true) ->when($invert, function ($query) { return $query ->where('e', '!=', 1) ->where('f', '<', 5) ->where(function ($query) { return $query->whereNotNull('g') ->where('h', '>=', 150); }); }, function ($query) { return $query ->where('e', '=', 1) ->orWhere('f', '>=', 5) ->orWhere(function ($query) { return $query->whereNull('g') ->orWhere('h', '<', 150); }); }); ``` With whereNot we can writte this query as: ``` $subquery = function ($query) { return $query ->where('e', '!=', 1) ->where('f', '<', 5) ->where(function ($query) { return $query->whereNotNull('g') ->where('h', '>=', 150); }); }; DB::table('table') ->where('b', true) ->when($invert, function ($query) use ($subquery) { return $query->whereNot($subquery); }, function ($query) use ($subquery) { return $query->where($subquery); }); DB::table('table') ->where('b', true) ->{$invert ? 'where' : 'whereNot'}($subquery); ``` Which is more simple and legible to read. We only allow calling whereNot in callback form: $query->whereNot($callback); because allowing the use as column `whereNot($column)` can confuse the developer since the behaviour of not() in some fields, like varchar, is different from php !$string. Resolve laravel/ideas#708
By adding this operator we can negate a complex query in a expressive way. For example, the query pointed by @DrowningElysium: `select * from table where b=true and NOT (e != 1 and f < 5 and (g != null and h >= 150))` To be done currently in laravel query builder it's necessary to invert all operators (`and` to `or`, `!=` to `==`, `<` to `>=`, `>=` to `<`). If we need to do the negation dynamically we will need to maintain two querys, increasing the possibility of bugs. For example: ``` DB::table('table') ->where('b', true) ->when($invert, function ($query) { return $query ->where('e', '!=', 1) ->where('f', '<', 5) ->where(function ($query) { return $query->whereNotNull('g') ->where('h', '>=', 150); }); }, function ($query) { return $query ->where('e', '=', 1) ->orWhere('f', '>=', 5) ->orWhere(function ($query) { return $query->whereNull('g') ->orWhere('h', '<', 150); }); }); ``` With whereNot we can writte this query as: ``` $subquery = function ($query) { return $query ->where('e', '!=', 1) ->where('f', '<', 5) ->where(function ($query) { return $query->whereNotNull('g') ->where('h', '>=', 150); }); }; DB::table('table') ->where('b', true) ->when($invert, function ($query) use ($subquery) { return $query->whereNot($subquery); }, function ($query) use ($subquery) { return $query->where($subquery); }); DB::table('table') ->where('b', true) ->{$invert ? 'where' : 'whereNot'}($subquery); ``` Which is more simple and legible to read. We only allow calling whereNot in callback form: $query->whereNot($callback); because allowing the use as column `whereNot($column)` can confuse the developer since the behaviour of not() in some fields, like varchar, is different from php !$string. Resolve laravel/ideas#708
By adding this operator we can negate a complex query in a expressive way. For example, the query pointed by @DrowningElysium: `select * from table where b=true and NOT (e != 1 and f < 5 and (g != null and h >= 150))` To be done currently in laravel query builder it's necessary to invert all operators (`and` to `or`, `!=` to `==`, `<` to `>=`, `>=` to `<`). If we need to do the negation dynamically we will need to maintain two querys, increasing the possibility of bugs. For example: ``` DB::table('table') ->where('b', true) ->when($invert, function ($query) { return $query ->where('e', '!=', 1) ->where('f', '<', 5) ->where(function ($query) { return $query->whereNotNull('g') ->where('h', '>=', 150); }); }, function ($query) { return $query ->where('e', '=', 1) ->orWhere('f', '>=', 5) ->orWhere(function ($query) { return $query->whereNull('g') ->orWhere('h', '<', 150); }); }); ``` With whereNot we can writte this query as: ``` $subquery = function ($query) { return $query ->where('e', '!=', 1) ->where('f', '<', 5) ->where(function ($query) { return $query->whereNotNull('g') ->where('h', '>=', 150); }); }; DB::table('table') ->where('b', true) ->when($invert, function ($query) use ($subquery) { return $query->whereNot($subquery); }, function ($query) use ($subquery) { return $query->where($subquery); }); DB::table('table') ->where('b', true) ->{$invert ? 'where' : 'whereNot'}($subquery); ``` Which is more simple and legible to read. We only allow calling whereNot in callback form: $query->whereNot($callback); because allowing the use as column `whereNot($column)` can confuse the developer since the behaviour of not() in some fields, like varchar, is different from php !$string. Resolve laravel/ideas#708
By adding this operator we can negate a complex query in a expressive way. For example, the query pointed by @DrowningElysium: `select * from table where b=true and NOT (e != 1 and f < 5 and (g != null and h >= 150))` To be done currently in laravel query builder it's necessary to invert all operators (`and` to `or`, `!=` to `==`, `<` to `>=`, `>=` to `<`). If we need to do the negation dynamically we will need to maintain two querys, increasing the possibility of bugs. For example: ``` DB::table('table') ->where('b', true) ->when($invert, function ($query) { return $query ->where('e', '!=', 1) ->where('f', '<', 5) ->where(function ($query) { return $query->whereNotNull('g') ->where('h', '>=', 150); }); }, function ($query) { return $query ->where('e', '=', 1) ->orWhere('f', '>=', 5) ->orWhere(function ($query) { return $query->whereNull('g') ->orWhere('h', '<', 150); }); }); ``` With whereNot we can write this query as: ``` $subquery = function ($query) { return $query ->where('e', '!=', 1) ->where('f', '<', 5) ->where(function ($query) { return $query->whereNotNull('g') ->where('h', '>=', 150); }); }; DB::table('table') ->where('b', true) ->when($invert, function ($query) use ($subquery) { return $query->whereNot($subquery); }, function ($query) use ($subquery) { return $query->where($subquery); }); // or just DB::table('table') ->where('b', true) ->{$invert ? 'where' : 'whereNot'}($subquery); ``` Which is more simple and legible. We only allow calling whereNot in callback form: $query->whereNot($callback); because allowing the use as column `whereNot($column)` can confuse the developer since the behaviour of not() in some fields, like varchar, is different from php !$string. Resolve laravel/ideas#708
By adding this operator we can negate a complex query in a expressive way. For example, the query pointed by @DrowningElysium: `select * from table where b=true and NOT (e != 1 and f < 5 and (g != null and h >= 150))` To be done currently in laravel query builder it's necessary to invert all operators (`and` to `or`, `!=` to `==`, `<` to `>=`, `>=` to `<`). If we need to do the negation dynamically we will need to maintain two querys, increasing the possibility of bugs. For example: ``` DB::table('table') ->where('b', true) ->when($invert, function ($query) { return $query ->where('e', '!=', 1) ->where('f', '<', 5) ->where(function ($query) { return $query->whereNotNull('g') ->where('h', '>=', 150); }); }, function ($query) { return $query ->where('e', '=', 1) ->orWhere('f', '>=', 5) ->orWhere(function ($query) { return $query->whereNull('g') ->orWhere('h', '<', 150); }); }); ``` With whereNot we can write this query as: ``` $subquery = function ($query) { return $query ->where('e', '!=', 1) ->where('f', '<', 5) ->where(function ($query) { return $query->whereNotNull('g') ->where('h', '>=', 150); }); }; DB::table('table') ->where('b', true) ->when($invert, function ($query) use ($subquery) { return $query->whereNot($subquery); }, function ($query) use ($subquery) { return $query->where($subquery); }); // or just DB::table('table') ->where('b', true) ->{$invert ? 'where' : 'whereNot'}($subquery); ``` Which is more simple and legible. We only allow calling whereNot in callback form: $query->whereNot($callback); because allowing the use as column `whereNot($column)` can confuse the developer since the behaviour of not() in some fields, like varchar, is different from php !$string. Resolve laravel/ideas#708
Would have liked to have this feature as I'm having to do a null safe NOT equal test (https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_equal-to). For standard not equal you can do ( |
Updated on 2020.06.15: <?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Bank extends Model
{
use \App\Traits\HasWhereNotTrait;
// Other stuff
} I know, this is an old question, but from my point of view, you can achieve your goal with As I understand, you want something like this:
SQL query will be:
But there is no whereNot, right? If so, you can simply use where method and pass
SQL query will be the same as I mentioned above. |
Background
In the Query Builder there are some type of NOT queries, like
whereNotIn()
,whereNotNull()
,whereNotBetween()
, andwhereNotExists()
. But there is nowhereNot()
.This makes it impossible to prioritize a query and then not allowing any of it to be true.
Like the following query:
select * from table where b=true and NOT (e != 1 and f < 5 and (g != null and h >= 150))
So my suggestion is to add this type of query.
The text was updated successfully, but these errors were encountered: