Reputation: 13562
I am working with Laravel and my current task is to get the Top 10 of songs played during last week.
$mostPlayed = Track::join('track_tracklist as pl', 'pl.track_id', '=', 'tracks.id')
->groupBy('tracks.id')
->orderBy('count','desc')
->take(10)
->get(['tracks.*', DB::raw('COUNT(pl.track_id) as count')]);
This query works fine, it returns me the 10 most played songs but without a date limitation. So I need to limit the connected tracklists with a given date (it should be compared with the date stored in tracklists) but I don't know how to add it.
Thank you :)
Update:
I came to a possible solution but it's not very efficient. The code above needs 0.009023904800415 seconds, the code below 0.96272301673889, needing 100% more time. Of course the code above is faster because it's not comparing the date but there should be a better way to solve the problem.
$time = '2015-05-01';
$elements = [];
$maxArray = [
'element' => null,
'count' => 0
];
for ($i = 0; $i < 10; $i++) {
$elements[] = $maxArray;
}
foreach (Track::all() as $track) {
$tracklists = $track->tracklists()->where('time', '>=', $time)->get();
for ($i = 0; $i < count($elements); $i++) {
if (count($tracklists) > $elements[$i]['count']) {
array_splice($elements, $i, 0, [[
'element' => $track,
'count' => count($tracklists)
]]);
array_pop($elements);
break;
}
}
}
SOLUTION jedrzej.kurylo was close to the solution, just forgetting one argument for the first join call:
$time = '2015-07-02';
$mostPlayed = Track::join('track_tracklist', 'track_tracklist.track_id', '=', 'tracks.id')
->join('tracklists', function ($join) use ($time) {
$join->on('tracklists.id', '=', 'track_tracklist.tracklist_id')->where('tracklists.time', '>=', $time);
})
->groupBy('tracks.id')
->orderBy('count', 'desc')
->take(10)
->get(['tracks.*', DB::raw('COUNT(track_tracklist.track_id) as count')]);
Will return the top 10 of tracks which are played between today and the given date needing 0.01 sec instead of 1 sec by doing with with a for each loop.
Upvotes: 0
Views: 293
Reputation: 40909
If you want to count only track_tracklist records from given daterange you'll need to apply additional constraints on the JOIN:
$time = '2015-05-01';
$mostPlayed = Track::join('track_tracklist as pl','pl.track_id', '=', 'tracks.id')
->join('tracklists', function($join) use ($time) {
$join->on('pl.tracklist_id', '=', 'tracklists.id');
$join->where('tracklists.time', '>=', $time)
})
->groupBy('tracks.id')
->orderBy('count','desc')
->take(10)
->get(['tracks.*', DB::raw('COUNT(pl.track_id) as count')]);
Upvotes: 1