I have a tasks table which tracks the car odometer values of a task. A task relates to itself and has one previous task defined by a has one relationship. I'm trying to create a scope to pull in a complete_at_odometer value in the query.
This value is equal to a completed_at_odometer value on the previous task plus the frequency of which the current task needs to be repeated. For example the current Task A needs to be completed every 10 miles. The last task, Task B was completed at 5 miles. I'm trying to create a scope to add the value complete_at_odometer to the results which should equal 15.
Here's what I have so far:
public function scopeWithCompleteByOdometer($query)
{
return $query
->join('tasks as oldTask', 'oldTask.current_task_id', '=', 'tasks.id')
->select(
'*',
'oldTask.completed_at_odometer as last_odometer',
'tasks.distance_interval as interval'
);
}
I'm not sure how can I add the values last_odometer and interval together whilst staying in the Database Layer of my application?
I'm using Laravel 7 and MySql 5.7.
Thanks for any help!
Using DB::raw query:
return $query
->join('tasks as oldTask', 'oldTask.current_task_id', '=', 'tasks.id')
->select(DB::raw('(oldTask.completed_at_odometer + tasks.distance_interval) AS total'));
OR take sum from the result obtained like this
$a = $row->completed_at_odometer;
$b = $row->distance_interval;
$total = $a+$b
I'm a system for a friend, but stumbled across a little problem.
I've got 3 models (customerCard, customerCardComment and customerCardFollowup).
It's better if you see the image below to understand what I'm trying to achieve. As you see I'm trying to get a result where I get a customerCard model where the sold field is equal to 0 and the customerCard model has no customerCardComment model where the type field is equal to 1,2 or 3, and the customerCard also does not have any customerCardFollowup.
Databases:
customer_cards
customer_card_comments
customer_card_followups
Both comments and followups table are related to the ID field in customer_cards. Both have foreign keys customer_card_id.
Is there a way to do this query? Or am i lost?
Thanks in advance.
Laravel's whereHas accepts a 3rd and 4th parameter. The 3rd parameter is the comparison operator against the count of the result set, and the 4th argument is the number to compare against. This will solve the first problem:
CustomerCard::where(function($query){
$query->where('sold', 0)
->whereHas('customerCardComment', function($query){
return $query->whereIn('type', [1,2,3]);
}, '=', 0);
});
Next, you can use ->has() to count the number of records returned from a relation, this will solve your second problem:
CustomerCard::where(function($query){
$query->where('sold', 0)
->whereHas('customerCardComment', function($query){
return $query->whereIn('type', [1,2,3]);
}, '=', 0)
->has('customerCardFollowup', '=', 0);
});
The 3rd one is actually a bit more complex and I need to think about how to approach that a bit more. I'll answer now to get you going in the right direction and edit and update the post with the solution to the 3rd problem shortly.
I have to get rows within a range of passed symbol no.
Image of Table from where query is to be done
Query:
Mark::select('users_id', 'symbol_no', 'mark_obtained')
->where('subject_trade_id', 2)
->whereBetween('symbol_no', [100, 1000])
->orderBy('symbol_no')
->get();
This query returns no data, but I was expecting total 9 rows form the query.
If I dump the query, I find the query as expected.
Query Log Image
If I run the generated query to mysql then it woks fine.
Again, if I change the symbol no. range to something like this:
Mark::select('users_id', 'symbol_no', 'mark_obtained')
->where('subject_trade_id', 2)
->whereBetween('symbol_no', [10, 1011])
->orderBy('symbol_no')
->get();
It returns 2 rows this time, and this output is also wrong.
If I try changing symbol no. range and query like this:
Mark::select('users_id', 'symbol_no', 'mark_obtained')
->where('subject_trade_id', 2)
->whereBetween('symbol_no', [101, 200])
->orderBy('symbol_no')
->get();
Now it works fine as expected.
Found the problem
By mistake the symbol_no column was defined as varchar() which had to be int() so, whereBetween() was being unable to return expected data.
I faced same problem.. Could you please check "symbol_no" field type in database table, It should be number/integer.
i have this table called dbo_modulesand it has columns ModuleCountLeft and ModuleCriticalLevel
in my controller, im trying to get the number of modules where ModuleCountLeft is less than the value of ModuleCriticalLevel. in my table, the values of ModuleCountLeft and ModuleCriticalLevel differs from row to row. so in my controller i uses this query:
$critical = DB::table('dbo_modules')
->where('ModuleCountLeft' , '<=' , DB::table('dbo_modules')->pluck('ModuleCriticalLevel') )
->count();
the problem here is that im not getting the correct values. It get the first ModuleCriticalLevel and makes it the point of comparison. for example the first ModuleCriticalLevel in the table is 20, it compares all the ModuleCountLeft to 20. Can anyone tell me what im doing wrong? or is my code wrong? please. Thanks in advance.
Try like following. You need not to pluck anything
$critical = DB::table('dbo_modules')
->where('ModuleCountLeft' ,'<=' ,'ModuleCriticalLevel')
->count();
How can I select a random row using Eloquent or Fluent in Laravel framework?
I know that by using SQL, you can do order by RAND(). However, I would like to get the random row without doing a count on the number of records prior to the initial query.
Any ideas?
Laravel >= 5.2:
User::inRandomOrder()->get();
or to get the specific number of records
// 5 indicates the number of records
User::inRandomOrder()->limit(5)->get();
// get one random record
User::inRandomOrder()->first();
or using the random method for collections:
User::all()->random();
User::all()->random(10); // The amount of items you wish to receive
Laravel 4.2.7 - 5.1:
User::orderByRaw("RAND()")->get();
Laravel 4.0 - 4.2.6:
User::orderBy(DB::raw('RAND()'))->get();
Laravel 3:
User::order_by(DB::raw('RAND()'))->get();
Check this article on MySQL random rows. Laravel 5.2 supports this, for older version, there is no better solution then using RAW Queries.
edit 1: As mentioned by Double Gras, orderBy() doesn't allow anything else then ASC or DESC since this change. I updated my answer accordingly.
edit 2: Laravel 5.2 finally implements a wrapper function for this. It's called inRandomOrder().
This works just fine,
$model=Model::all()->random(1)->first();
you can also change argument in random function to get more than one record.
Note: not recommended if you have huge data as this will fetch all rows first and then returns random value.
tl;dr: It's nowadays implemented into Laravel, see "edit 3" below.
Sadly, as of today there are some caveats with the ->orderBy(DB::raw('RAND()')) proposed solution:
It isn't DB-agnostic. e.g. SQLite and PostgreSQL use RANDOM()
Even worse, this solution isn't applicable anymore since this change:
$direction = strtolower($direction) == 'asc' ? 'asc' : 'desc';
edit: Now you can use the orderByRaw() method: ->orderByRaw('RAND()'). However this is still not DB-agnostic.
FWIW, CodeIgniter implements a special RANDOM sorting direction, which is replaced with the correct grammar when building query. Also it seems to be fairly easy to implement. Looks like we have a candidate for improving Laravel :)
update: here is the issue about this on GitHub, and my pending pull request.
edit 2: Let's cut the chase. Since Laravel 5.1.18 you can add macros to the query builder:
use Illuminate\Database\Query\Builder;
Builder::macro('orderByRandom', function () {
$randomFunctions = [
'mysql' => 'RAND()',
'pgsql' => 'RANDOM()',
'sqlite' => 'RANDOM()',
'sqlsrv' => 'NEWID()',
];
$driver = $this->getConnection()->getDriverName();
return $this->orderByRaw($randomFunctions[$driver]);
});
Usage:
User::where('active', 1)->orderByRandom()->limit(10)->get();
DB::table('users')->where('active', 1)->orderByRandom()->limit(10)->get();
edit 3: Finally! Since Laravel 5.2.33 (changelog, PR #13642) you can use the native method inRandomOrder():
User::where('active', 1)->inRandomOrder()->limit(10)->get();
DB::table('users')->where('active', 1)->inRandomOrder()->limit(10)->get();
You can use:
ModelName::inRandomOrder()->first();
it's very simple just check your laravel version
Laravel >= 5.2:
User::inRandomOrder()->get();
//or to get the specific number of records
// 5 indicates the number of records
User::inRandomOrder()->limit(5)->get();
// get one random record
User::inRandomOrder()->first();
or using the random method for collections:
User::all()->random();
User::all()->random(10); // The amount of items you wish to receive
Laravel 4.2.7 - 5.1:
User::orderByRaw("RAND()")->get();
Laravel 4.0 - 4.2.6:
User::orderBy(DB::raw('RAND()'))->get();
Laravel 3:
User::order_by(DB::raw('RAND()'))->get();
In Laravel 4 and 5 the order_by is replaced by orderBy
So, it should be:
User::orderBy(DB::raw('RAND()'))->get();
For Laravel 5.2 >=
use the Eloquent method:
inRandomOrder()
The inRandomOrder method may be used to sort the query results randomly. For example, you may use this method to fetch a random user:
$randomUser = DB::table('users')
->inRandomOrder()
->first();
from docs: https://laravel.com/docs/5.2/queries#ordering-grouping-limit-and-offset
You can also use order_by method with fluent and eloquent like as:
Posts::where_status(1)->order_by(DB::raw(''),DB::raw('RAND()'));
This is a little bit weird usage, but works.
Edit: As #Alex said, this usage is cleaner and also works:
Posts::where_status(1)->order_by(DB::raw('RAND()'));
Use Laravel function
ModelName::inRandomOrder()->first();
You can easily Use this command:
// Question : name of Model
// take 10 rows from DB In shuffle records...
$questions = Question::orderByRaw('RAND()')->take(10)->get();
There is also whereRaw('RAND()') which does the same, you can then chain ->get() or ->first() or even go crazy and add ->paginate(int).
I prefer to specify first or fail:
$collection = YourModelName::inRandomOrder()
->firstOrFail();
Laravel has a built-in method to shuffle the order of the results.
Here is a quote from the documentation:
shuffle()
The shuffle method randomly shuffles the items in the collection:
$collection = collect([1, 2, 3, 4, 5]);
$shuffled = $collection->shuffle();
$shuffled->all();
// [3, 2, 5, 1, 4] - (generated randomly)
You can see the documentation here.
At your model add this:
public function scopeRandomize($query, $limit = 3, $exclude = [])
{
$query = $query->whereRaw('RAND()<(SELECT ((?/COUNT(*))*10) FROM `products`)', [$limit])->orderByRaw('RAND()')->limit($limit);
if (!empty($exclude)) {
$query = $query->whereNotIn('id', $exclude);
}
return $query;
}
then at route/controller
$data = YourModel::randomize(8)->get();
I have table with thousands of records, so I need something fast. This is my code for pseudo random row:
// count all rows with flag active = 1
$count = MyModel::where('active', '=', '1')->count();
// get random id
$random_id = rand(1, $count - 1);
// get first record after random id
$data = MyModel::where('active', '=', '1')->where('id', '>', $random_id)->take(1)->first();
Here's how I get random results in eloquent in one of my projects:
$products = Product::inRandomOrder()->limit(10);
10 - The number of random records to pull.
Try this code! It Works:
User::orderBy(DB::raw('RAND()'))->get();