I have two tables. I would like to get the values of the counts of these two rows (attacker, victim) from the first table and their respective userid from the second table, if possible.
Table1:
id----attacker---victim
1-----1216-------1040
1-----1216-------1024
1-----1040-------1024
1-----1040-------1024
1-----1024-------1216
1-----1216-------1024
Table2:
id----name----userid
1-----John----1216
2-----Joe-----1024
3-----Peter---1040
So far I only managed to get the values of the counts of rows attacker and victim but I achieved it using two separate queries. Is it possible to do this with just one query?
$victims = DB::table('Table1')
->select(DB::raw('victim as userid, count(victim) as victims'))
->where('victim', '<>', 1)
->groupBy('victim')
->get();
$attackers = DB::table('Table1')
->select(DB::raw('attacker as userid, count(attacker) as attackers'))
->where('attacker', '<>', 1)
->groupBy('attacker')
->get();
Basically what I am aiming for is to get something like this in the end:
name----------(count of attacker)-----(count of victim)
John-----------3----------------------1
Joe------------1----------------------4
Peter----------2----------------------1
UPDATE:
After some time I managed to get name + victims and name + attackers but separate by using the code below:
$kills = DB::table('Table2')
->join('Table1', 'Table2.roleid', '=', 'Table1.attacker')
->select(DB::raw('Table2.name, count(Table1.attacker) as kills'))
->groupBy('Table2.name')
->orderBy('kills', 'desc')
->get();
$deaths = DB::table('Table2')
->join('Table1', 'Table2.roleid', '=', 'Table1.victim')
->select(DB::raw('Table2.name, count(Table1.victim) as deaths'))
->groupBy('Table2.name')
->orderBy('deaths', 'desc')
->get();
Advertisement
Answer
After some hours of researching I think I somehow managed to find a solution. I just had to use relationships.
On Table 2 Model:
public function kills()
{
return $this->hasMany('Kill', 'attacker', 'userid');
}
public function deaths()
{
return $this->hasMany('Kill', 'victim', 'userid');
}
then I used the following code to get the results I wanted:
$results = Table2::select('name')
->whereHas('kills')->orWhereHas('deaths')
->withCount(['kills'=> $query])
->withCount(['deaths'=> $query])
->orderBy('kills_count', 'desc')
->get();
return $results->toArray();
I’ll also post the RAW SQL query incase anyone could benefit from it
SELECT
`name`,
(
SELECT
COUNT(*)
FROM
`Table1`
WHERE
`Table2`.`userid` = `Table1`.`attacker`
)
AS `kills_count`,
(
SELECT
COUNT(*)
FROM
`Table1`
WHERE
`Table2`.`userid` = `Table1`.`victim`
)
AS `deaths_count`
FROM
`Table2`
WHERE
EXISTS
(
SELECT
*
FROM
`Table1`
WHERE
`Table2`.`userid` = `Table1`.`attacker`
)
OR EXISTS
(
SELECT
*
FROM
`Table1`
WHERE
`Table2`.`userid` = `Table1`.`victim`
)
ORDER BY
`kills_count` DESC
If anyone knows how to further improve this query for performance, please let me know.