Laravel 4.2
Here are my tables
sk__queue :
+----------+----------+---------------------+--------+
| idQueue | idCap | date | status |
+----------+----------+---------------------+--------+
| 1350 | 7 | 2015-10-20 11:20:00 | 9 |
| 1427 | 7 | 2015-10-29 14:20:00 | 4 |
| 1428 | 7 | 2015-10-29 14:19:00 | 4 |
+----------+----------+---------------------+--------+
sk__cloc
+----------+----------+-----------+-----+---------------------+--------------------------+
| idCloc | idCap | cDuration | cNb | begin | end |
+----------+----------+-----------+-----+---------------------+--------------------------+
| 1 | 7 | 10 | 3 | 2015-01-01 08:00:00 | 2015-12-31 22:30:00 |
+----------+----------+-----------+-- --+---------------------+--------------------------+
A spot is available if the sk__queue.status is < 4 or > 7
I want to know how many spots are available between the last 10 minutes and 10 minutes in the future.
My Eloquent query is like that :
//$now = date('Y-m-d H:i:s');
$now = "2015-10-29 14:12:08";
$dispo = DB::table('sk__cloc')->leftJoin('sk__queue', function($join) use ($now) {
$join->on('sk__queue.idCap', '=', 'sk__cloc.idCap');
$join->where('sk__queue.date', '>=', "('$now' - INTERVAL cDuration MINUTE)");
$join->where('sk__queue.date', '<=', "('$now' + INTERVAL cDuration MINUTE)");
$join->where('sk__queue.date', '>=', 'sk__cloc.begin');
$join->where('sk__queue.date', '<=', 'sk__cloc.end');
$join->where('sk__queue.status', '>=', 4);
$join->where('sk__queue.status', '<=', 7);
})
->where('sk__cloc.idCap', '=', 7)
->groupBy('cNb')
->select(DB::raw('cNb*2, count(sk__queue.idCap) AS count'))
->first();
Result : "cNb*2":6, "count":0
Now I'm doing DB::getQueryLog() and this is the laravel request :
select cNb*2, count(sk__queue.idCap) AS count, sk__queue.date
from `sk__cloc` left join `sk__queue`
on `sk__queue`.`idCap` = `sk__cloc`.`idCap`
and `sk__queue`.`date` >= ('2015-10-29 14:12:08' - INTERVAL cDuration MINUTE)
and `sk__queue`.`date` <= ('2015-10-29 14:12:08' + INTERVAL cDuration MINUTE)
and `sk__queue`.`date` <= sk__cloc.end
and `sk__queue`.`status` >= 4
and `sk__queue`.`status` <= 7
where `sk__cloc`.`idCap` = 7
group by cNb
In PhpMyAdmin, the result is : "cNb*2":6, "count":2
Then I commented those lines :
//$now = date('Y-m-d H:i:s');
$now = "2015-10-29 14:12:08";
$dispo = DB::table('sk__cloc')->leftJoin('sk__queue', function($join) use ($now) {
$join->on('sk__queue.idCap', '=', 'sk__cloc.idCap');
$join->where('sk__queue.date', '>=', "('$now' - INTERVAL cDuration MINUTE)");
//$join->where('sk__queue.date', '<=', "('$now' + INTERVAL cDuration MINUTE)");
//$join->where('sk__queue.date', '>=', 'sk__cloc.begin');
$join->where('sk__queue.date', '<=', 'sk__cloc.end');
$join->where('sk__queue.status', '>=', 4);
$join->where('sk__queue.status', '<=', 7);
})
->where('sk__cloc.idCap', '=', 7)
->groupBy('cNb')
->select(DB::raw('cNb*2, count(sk__queue.idCap) AS count'))
->first();
Result : "cNb*2":6, "count":2
My only question is : What is happining right here ?! I'm so confused.
Thanks for your help.
You should keep joining "on":
$join->on('sk__queue.idCap', '=', 'sk__cloc.idCap');
$join->on('sk__queue.date', '>=', "('$now' - INTERVAL cDuration MINUTE)");
$join->on('sk__queue.date', '<=', "('$now' + INTERVAL cDuration MINUTE)");
$join->on('sk__queue.date', '>=', 'sk__cloc.begin');
$join->on('sk__queue.date', '<=', 'sk__cloc.end');
$join->on('sk__queue.status', '>=', 4);
$join->on('sk__queue.status', '<=', 7);
Related
I have two table
1. news_categories
+----+---------------------+
| id | created_at |
+----+---------------------+
| 1 | 2020-10-10 10:10:10 |
+----+---------------------+
2. news_category_translations
+----+--------+---------------+---------+
| id | map_id | language_code | name |
+----+--------+---------------+---------+
| 1 | 1 | vi | name vi |
| 2 | 1 | en | name en |
+----+--------+---------------+---------+
How do I fix the looping condition in this code
$locale = \App::getLocale()
$category = \App\Models\NewsCategory::with(['translation' => function($q){
$q->where('language_code', 'en'); // duplicate (1)
}])->whereHas('translation', function($q){
$q->where('language_code', 'en'); // duplicate (2)
})->find(1);
Model NewCategory
public function translation()
{
return $this->hasOne('App\Models\NewsCategoryTranslation', 'map_id', 'id');
}
I don't want to push conditional on the model.
Update 1:
When i remove condition (1) output:
newsCategory ['id' => 1, 'translation' => ['id' => 1]] false because language_code = en
When i remove condition (2) and delete translation with id = 2 ouput:
newsCategory ['id' => 1, 'translation' => null] => false because record with language_code = en does not exist
When I use both conditions, the result is as expected. Why?
Sorry my english is quite bad and i don't have much experience with laravel. Thanks.
Update 2:
I have referenced the following article
https://medium.com/#amritms/combining-wherehas-and-with-in-laravel-eloquent-c91391bd3c02
And i see author use
$callback = function($query) {
$query->where('something', '=', 'something');
}
$submissions = Post::whereHas('submissions', $callback)->with(['submissions' => $callback])->get();
If don't use it callback function it will be the same for me, duplicate condition from with and whereHas.
i have a table remaining_bus_fees.
id | date | student_id | remaining_balance
-----------------------------------------------------
1 | 2019-04-05 | 1 | 500
2 | 2019-05-10 | 2 | 400
3 | 2019-05-13 | 3 | 300
Now i need how to get last month record against student_id. here is
query i am using. but this is not working for me.
$remain_fee = \DB::table('remaining_bus_fees')
->whereMonth('date', '<', Carbon::now()->subMonth()->month)
->where('student_id', '=', 2)->get();
Here is useful queries :
$today=DB::table('remaining_bus_fees')->whereRaw('Date(created_at) = CURDATE()')->where('student_id', 2)->get();
$yesterday= DB::table('remaining_bus_fees')->whereDate('created_at',Carbon::yesterday())->get();
$last_7_days= DB::table('remaining_bus_fees')->whereBetween('created_at', [Carbon::now()->startOfWeek(), Carbon::now()->endOfWeek()])->get();
$this_month=DB::table('remaining_bus_fees')->whereMonth('created_at',Carbon::now()->month)->whereYear('created_at', date('Y'))->where('student_id', 2)->get();
$last_month=DB::table('remaining_bus_fees')->whereMonth('created_at',Carbon::now()->subMonth()->format('m'))->whereYear('created_at', date('Y'))->where('student_id', 2)->get();
Change your code to this and it should work fine, you need to convert your Carbon::now() to date format as you will use whereDate here, it will consider only date.
$remain_fee = \DB::table('remaining_bus_fees')
->whereDate('date', '<', Carbon::now()->subMonth()->toDateString())
->where('student_id', '=', 2)->get();
Example in tinker
>>> App\User::whereDate('created_at', Carbon\Carbon::now()->subMonth()->toDateSt
ring())->get()
=> Illuminate\Database\Eloquent\Collection {#3120
all: [
App\User {#3114
id: 90,
name: "******",
email: "******#gmail.com",
created_at: "2019-05-01 06:17:47",
updated_at: "2019-05-02 00:28:18",
},
],
}
>>>
Try this out,
$remain_fee = \DB::table('remaining_bus_fees')
->whereMonth('date', '=', Carbon::now()->subMonth()->month)
->whereStudentId(2)->get();
At the minute your code is saying where date is "before a month ago" whereas it should be where the date is a month ago (i.e. remove <). Also, I would suggest adding the year to the query as well otherwise you'll start to get previous years results.
This should get you what you need:
$date = Carbon::now()->subMonth();
$remain_fee = \DB::table('remaining_bus_fees')
->whereMonth('date', $date->month)
->whereYear('date', $date->year)
->where('student_id', 2)
->get();
+---------+--------+---------+---------+
| date | type_a | type_b | type_zzz|
+---------+--------+---------+---------+
|01-01-18 | 12 | 10 | 1 |
|02-01-18 | 2 | 5 | 1 |
|03-01-18 | 7 | 2 | 2 |
|01-02-18 | 13 | 6 | 55 |
|02-02-18 | 22 | 33 | 5 |
+---------+--------+---------+---------+
Hi,
In above example, I would like to know if it's possible to groupBy month and sum each column when getting results in Laravel (tables are dynamic so there are no models for them and also some tables don't have column 'type_a' other don't have 'type_zzz' etc...).
What I'm looking to get from above table is something like this:
"01" =>
'type_a' : '21',
'type_b' : '17',
'type_zzz': '4'
"02" =>
'type_a' : '35',
'type_b' : '39',
'type_zzz': '60'
I'm using following code to group it by month but I'm not able to find solution to return sum by each column:
DB::table($id)->get()->groupBy(function($date) {
return Carbon::parse($date->repdate)->format('m');;
});
If I understand your question correctly, you can either group and sum the values using an SQL query:
$grouped = DB::table('table_name')
->selectRaw('
SUM(type_a) AS type_a,
SUM(type_b) AS type_b,
SUM(type_z) AS type_z
')
->groupByRaw('MONTH(date)')
->get();
Or if you don't want to have to specify the column names in each query, you can use groupBy, array_column, and array_sum on your collection:
$grouped = DB::table('table_name')
->get()
->groupBy(function ($item) {
return Carbon::parse($item->date)->format('m');
})
->map(function ($group) {
$group = $group->toArray();
$summed = [];
$columns = array_keys($group[0]);
array_shift($columns);
foreach ($columns as $column) {
$summed[$column] = array_sum(array_column($group, $column));
}
return $summed;
});
I have an events table with 4 events all with different start and enddate.
mysql> select id, event_name, event_startdate, event_closedate from events;
+----+--------------+---------------------+---------------------------+
| id | event_name | event_startdate | event_closedate |
+----+--------------+---------------------+---------------------------+
| 1 | Event 1 | 2016-05-01 00:00:00 | 2016-06-30 00:00:00 |
| 2 | Event 2 | 2016-06-01 00:00:00 | 2016-07-30 00:00:00 |
| 3 | Event 3 | 2016-07-01 00:00:00 | 2016-08-30 00:00:00 |
| 4 | Event 4 | 2016-09-01 00:00:00 | 2016-10-30 00:00:00 |
+----+--------------+---------------------+---------------------------+
I want to return the current events. In MySQL, the below query works:
mysql> select id, event_name, event_startdate, event_closedate from events where now() >= event_startdate and now() <= event_closedate;
+----+--------------+---------------------+---------------------------+
| id | event_name | event_startdate | event_closedate |
+----+--------------+---------------------+---------------------------+
| 1 | Event 1 | 2016-05-01 00:00:00 | 2016-06-30 00:00:00 |
| 2 | Event 2 | 2016-06-01 00:00:00 | 2016-07-30 00:00:00 |
+----+--------------+---------------------+---------------------------+
Now, I want to create the Eloquent equivalent. I have created the following:
$current_events = DB::table('events')->select('id','event_name', 'event_startdate', 'event_closedate')->where(DB::raw('now()'), '>=', 'event_startdate')->where(DB::raw('now()'), '<=', 'event_closedate')->get();
When I do a 'dd' output in Laravel, I get:
"select `id`, `event_name`, `event_startdate`, `event_closedate` from `events` where now() >= ? and now() <= ?"
The above is pretty similar to the query in MySQL that returns the two current events, so I was expecting to see the two events in my view but nothing is being output so I suspect I'm doing something wrong
The view is:
#foreach( $current_events as $event )
<tr>
<td align="center" class="hidden-xs">{{ $event->id }}</td>
<td>{{ $event->event_name }}</td>
<td>{{ $event->event_startdate }}</td>
<td>{{ $event->event_closedate) }}</td>
</tr>
#endforeach
Any reason why this does not return the two current events?
Did you try
$current_events = DB::table('events')->select( 'id','event_name', 'event_startdate', 'event_closedate' )
->where( DB::raw('now()'), '>=', DB::raw('event_startdate') )
->where( DB::raw('now()'), '<=', DB::raw('event_closedate') )->get();
It will be better if you use query scopes inside your eloquent model, scopes makes your code easier to understand and works better than raw queries in your case. For example, in your model you should do:
class Event extends Model
{
...
public function scopeCurrent($query)
{
return $query->where('event_startdate', '<=', Carbon\Carbon::now())
->where('event_closedate', '>=', Carbon\Carbon::now());
}
...
}
And anywhere in your controller:
class EventController extends Controller
{
/**
* Display a listing of the resource.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function index(Request $request)
{
$todayEvents = Event::current()->select('id', 'event_name', 'event_startdate', 'event_closedate')->get();
...
}
}
If you're having issues with Carbon, check the docs.
The correct query to use is:
$current_events = DB::table('events')->select( 'id','event_name', 'event_startdate', 'event_closedate' )
->where( DB::raw('now()'), '>=', DB::raw('event_startdate') )
->where( DB::raw('now()'), '<=', DB::raw('event_closedate') )->get();
instead of
$current_events = DB::table('events')->select('id','event_name', 'event_startdate', 'event_closedate')
->where(DB::raw('now()'), '>=', 'event_startdate')
->where(DB::raw('now()'), '<=', 'event_closedate')->get();
Because Laravel uses Carbon dates.. this is a better solution. It also uses Eloquent models, rather than the DB class.
$current_event = Events::select( 'id','event_name', 'event_startdate', 'event_closedate' )
->where('event_startdate', '<=', Carbon::now())
->where('event_closedate', '>=', Carbon::now())->get();
I'm trying to create an Eloquent query that gets the total number of posts made each distinct day, and if the date is missing, fill it in with a value of zero.
For example, if my table looks like this:
+----+---------------------+
| id | date |
+----+---------------------+
| 1 | 2015-01-01 00:00:00 |
| 2 | 2015-01-01 01:53:18 |
| 3 | 2015-01-01 02:41:26 |
| 4 | 2015-01-02 12:51:01 |
| 5 | 2015-01-05 08:24:12 |
+----+---------------------+
This would output:
2015-01-01 : 3
2015-01-02 : 1
2015-01-05 : 1
Notice, however, that the days 03-04 are missing. How can I include these dates, but give them the value 0 such that I end up with an output like:
2015-01-01 : 3
2015-01-02 : 1
2015-01-03 : 0
2015-01-04 : 0
2015-01-05 : 1
Here is my current query:
$posts = Post::select(array(
DB::raw('DATE(`created_at`) as `date`'),
DB::raw('COUNT(*)as `count`')
))
->where('created_at', '>', Carbon::today()->subWeek())
->groupBy('date')
->orderBy('date', 'DESC')
->lists('count', 'date');
Thanks!
In your SQL results you can generate some "fake-data" in your rows, but u can not generate "fake-rows", exept joining to some "fake(temporary)-table".
In your case ll be much easier to apply some logic around sql-result.
Replace your code with this:
$order = 'DESC';
$endDate = Carbon::today();
$startDate = Carbon::today()->subWeek();
$dateInc = ($order == 'DESC') ? -1 : 1;
$dateCycleHolder = clone ($dateInc > 0 ? $startDate : $endDate);
$dateCycleEnd = clone ($dateInc > 0 ? $endDate : $startDate);
$posts = Post::select(array(
DB::raw('DATE(`created_at`) as `date`'),
DB::raw('COUNT(*)as `count`')
))
->where('created_at', '>', $startDate)
->groupBy('date')
->orderBy('date', $order)
->lists('count', 'date');
$postsFinal = new \Illuminate\Database\Eloquent\Collection();
while ($dateCycleHolder->ne($dateCycleEnd)) {
$dateCurr = $dateCycleHolder->format('Y-m-d');
$postsFinal->put($dateCurr, $posts->get($dateCurr, 0));
$dateCycleHolder->addDay($dateInc);
}
$dateCurr = $dateCycleHolder->format('Y-m-d');
$postsFinal->put($dateCurr, $posts->get($dateCurr, 0));
$posts = $postsFinal;
its alittle bit flexible, you can change values of this things:
$order = 'DESC';
$endDate = Carbon::today();
$startDate = Carbon::today()->subWeek();