items : id, name
пользователей : id, username
user_items : id, user_id, item_id
В настоящее время у меня есть count()
на user_items
который показывает пользователей с наибольшим количеством элементов:
john: 13 bill: 9 lily: 9 kent: 9 seth: 8 vick: 8 anna: 7
Но я хочу показать его таким образом:
13: john 9: bill, lily, kent 8: seth, vick 7: anna
Как я могу достичь этого с помощью системы запросов laravel в клинке?
В контроллере получится так
$users = DB::table('user_items as ui') ->select('count',DB::raw("group_concat(name SEPARATOR ', ') as names")) ->from(DB::raw('(select count(*) as count,u.username as name from user_items ui join users u on u.id=ui.user_id group by u.id) a')) ->groupBy('count') ->orderBy('count','desc') ->get(); $data['users']=$users; return View::make('hello',$data);
по$users = DB::table('user_items as ui') ->select('count',DB::raw("group_concat(name SEPARATOR ', ') as names")) ->from(DB::raw('(select count(*) as count,u.username as name from user_items ui join users u on u.id=ui.user_id group by u.id) a')) ->groupBy('count') ->orderBy('count','desc') ->get(); $data['users']=$users; return View::make('hello',$data);
С учетом использования лезвия
@foreach($users as $user) <li>{{$user->count.':'. $user->names}}</li> @endforeach
Если вы хотите, чтобы пользователи, у которых нет элемента для отображения, могут быть запрошены
$users = DB::table('users as u') ->select('count',DB::raw("group_concat(name SEPARATOR ', ') as names")) ->from(DB::raw('(select count(ui.item_id) as count,u.username as name from users u left join user_items ui on u.id=ui.user_id group by u.id) a')) ->groupBy('count') ->orderBy('count','desc') ->get();
по$users = DB::table('users as u') ->select('count',DB::raw("group_concat(name SEPARATOR ', ') as names")) ->from(DB::raw('(select count(ui.item_id) as count,u.username as name from users u left join user_items ui on u.id=ui.user_id group by u.id) a')) ->groupBy('count') ->orderBy('count','desc') ->get();
Для отображения имен отдельно добавьте следующий код до $data['users']=$users;
foreach($users as $user){ $user->names=explode(', ',$user->names); }
И в лезвии вы можете
<ul> @foreach($users as $user) <li> <span>{{$user->count}}:</span> @foreach($user->names as $index=>$name) <span><a href="#">{{$name}}</a> @if($index!=count($user->names)-1) ,@endif </span> @endforeach </li> @endforeach </ul>
Не уверен в Laravel, но это чистая версия MySQL:
SELECT itemCount, GROUP_CONCAT(username) FROM ( SELECT tblU.user_name, COUNT([DISTINCT] tblUI.item_id) AS itemCount FROM users AS tblU INNER JOIN user_items AS tblUI ON tblU.id = tblUI.user_id GROUP BY tblU.user_name ) AS uic GROUP BY itemCount
Примечание. DISTINCT является необязательным, поэтому квадратные скобки. Кроме того, если вы хотите, чтобы пользователи без каких-либо элементов, вы можете сделать JOIN LEFT JOIN.
Простейшим может быть обработка результата DB с помощью PHP:
$result = []; foreach ($db_result as $name => $item_count) { $result[$item_count][] = $name; }
Затем, чтобы получить ожидаемый результат, вы можете захотеть следовать с помощью implode()
:
foreach ($result as &$names) { $names = implode(', ', $names); }
Логика моего решения такая же, как и Uueerdo, но улучшение читаемости, я также пытаюсь использовать только один запрос (без вложенных), но не добиваться успеха.
select itemCount,group_concat(username) as userNames from ( SELECT username,COUNT(1) AS itemCount FROM users AS u INNER JOIN user_items AS ui ON u.id =ui.user_id GROUP BY u.id ) as tempTab group by itemCount
Просмотреть sql в SQL Fiddle