复杂查询 3 个表,其中 2 个 INNER JOIN、1 个子查询、2 个分组 Laravel
Complex query 3 tables with 2 INNER JOIN, 1 subquery, 2 Group By in Laravel
这是我最后一次尝试在 Laravel 中创建复杂查询。对于这种情况,我需要 3 个表:photos, events, countries
。每个事件有很多或 none 张照片,每个国家可能有多个带有照片的事件。
我的结果显示
PhotosByCountry, EventsByCountry, rContinent, rCountry.
这是运行良好的 MySQL 本机查询:
SELECT SUM( allPhotos ) AS PhotosByCountry,
COUNT( temp.Land ) AS EventsByCountry,
rContinent,
temp.Land AS rCountry
FROM (
SELECT e.country AS Land, COUNT( p.id ) AS allPhotos, c.continent AS rContinent
FROM `photos` p
INNER JOIN `events` e ON e.id = p.eventID
INNER JOIN countries c ON e.country = c.country
GROUP BY p.eventID
)temp
GROUP BY rCountry
谁能帮我将其翻译成 Laravel 查询生成器而不用 DB::raw()
或 whereRaw()
。我构建那个东西的主要问题是子查询。
我得到了所有表的 Models
:Photo, Country, Sportevent (for table events (= legacy name), couldn't use Event)
。
感谢您的努力,如果需要,我很乐意提供更多信息。
加法
表格:
events
id | name | country ... has more columns of course
1 | Eventname 1 | France
2 | Eventname 2 | Switzerland
3 | Eventname 3 | France
photos
id | eventID | path ...
1 | 2 | .....
2 | 1 | .....
3 | 2 | .....
4 | 3 | .....
5 | 3 | .....
6 | 2 | .....
countries
id | country | continent (or geographical Region) ...
1 | France | Europe
2 | Switzerland | Europe
3 | Germany | Europe
4 | United States| North America
5 | Australia | Oceania
6 | .....
Result
PhotosByCountry | EventsByCountry | rContinent | rCountry
3 | 2 | Europe | France
3 | 1 | Europe | Switzerland
试试这个:
国家模式
protected function photosCount()
{
return $this->hasManyThrough('photos', 'events', 'country', 'event_id')
->groupBy('countries.country')
->count();
}
public function getPhotosCount() {
return $this->photosCount ? $this->photosCount->count : 0;
}
protected function eventsCount()
{
return $this->hasMany('events', 'country', 'event_id')
->groupBy('countries.country')
->count();
}
public function getEventsCount() {
return $this->eventsCount ? $this->eventsCount->count : 0;
}
像这样访问它:
$countries = Country::with('photosCount', 'eventsCount')->get();
$countries->first()->getPhotosCount();
$countries->first()->getEventsCount();
代码未经测试。
来源:http://laravel.io/forum/05-03-2014-eloquent-get-count-relation
这可能会进行 3 sql 次查询,而不是 1 次(一次针对国家/地区 + 2 次 WHERE IN 查询与计数)。但我认为这是获得计数的一种非常好的方式。
完成问题:
因为在 Eloquent 查询生成器中构建我的初始查询似乎不可能或太复杂,所以我在我的 Photo
模型中使用了以下函数(但我可以将它放在任何其他型号)
public function allCountrysWithPhotos(){
$rawQuery=" SELECT SUM( allPhotos ) AS PhotosByCountry,
COUNT( temp.Land ) AS EventsByCountry,
rContinent,
temp.Land AS rCountry
FROM (
SELECT e.country AS Land,
COUNT( p.id ) AS allPhotos,
c.continent AS rContinent
FROM `photos` p
INNER JOIN `events` e ON e.id = p.eventID
INNER JOIN countries c ON e.country = c.country
GROUP BY p.eventID
)temp
GROUP BY rCountry
ORDER BY rContinent, rCountry";
return DB::select($rawQuery);
}
如果将来需要调整某些内容(索引可能在某个阶段),这对 SQL 用户来说很有效并且很容易理解。
无论如何,谢谢你的努力,我不会再问 Eloquent 问题了,而是用原生查询来代替。
这是我最后一次尝试在 Laravel 中创建复杂查询。对于这种情况,我需要 3 个表:photos, events, countries
。每个事件有很多或 none 张照片,每个国家可能有多个带有照片的事件。
我的结果显示
PhotosByCountry, EventsByCountry, rContinent, rCountry.
这是运行良好的 MySQL 本机查询:
SELECT SUM( allPhotos ) AS PhotosByCountry,
COUNT( temp.Land ) AS EventsByCountry,
rContinent,
temp.Land AS rCountry
FROM (
SELECT e.country AS Land, COUNT( p.id ) AS allPhotos, c.continent AS rContinent
FROM `photos` p
INNER JOIN `events` e ON e.id = p.eventID
INNER JOIN countries c ON e.country = c.country
GROUP BY p.eventID
)temp
GROUP BY rCountry
谁能帮我将其翻译成 Laravel 查询生成器而不用 DB::raw()
或 whereRaw()
。我构建那个东西的主要问题是子查询。
我得到了所有表的 Models
:Photo, Country, Sportevent (for table events (= legacy name), couldn't use Event)
。
感谢您的努力,如果需要,我很乐意提供更多信息。
加法
表格:
events
id | name | country ... has more columns of course
1 | Eventname 1 | France
2 | Eventname 2 | Switzerland
3 | Eventname 3 | France
photos
id | eventID | path ...
1 | 2 | .....
2 | 1 | .....
3 | 2 | .....
4 | 3 | .....
5 | 3 | .....
6 | 2 | .....
countries
id | country | continent (or geographical Region) ...
1 | France | Europe
2 | Switzerland | Europe
3 | Germany | Europe
4 | United States| North America
5 | Australia | Oceania
6 | .....
Result
PhotosByCountry | EventsByCountry | rContinent | rCountry
3 | 2 | Europe | France
3 | 1 | Europe | Switzerland
试试这个:
国家模式
protected function photosCount()
{
return $this->hasManyThrough('photos', 'events', 'country', 'event_id')
->groupBy('countries.country')
->count();
}
public function getPhotosCount() {
return $this->photosCount ? $this->photosCount->count : 0;
}
protected function eventsCount()
{
return $this->hasMany('events', 'country', 'event_id')
->groupBy('countries.country')
->count();
}
public function getEventsCount() {
return $this->eventsCount ? $this->eventsCount->count : 0;
}
像这样访问它:
$countries = Country::with('photosCount', 'eventsCount')->get();
$countries->first()->getPhotosCount();
$countries->first()->getEventsCount();
代码未经测试。
来源:http://laravel.io/forum/05-03-2014-eloquent-get-count-relation
这可能会进行 3 sql 次查询,而不是 1 次(一次针对国家/地区 + 2 次 WHERE IN 查询与计数)。但我认为这是获得计数的一种非常好的方式。
完成问题:
因为在 Eloquent 查询生成器中构建我的初始查询似乎不可能或太复杂,所以我在我的 Photo
模型中使用了以下函数(但我可以将它放在任何其他型号)
public function allCountrysWithPhotos(){
$rawQuery=" SELECT SUM( allPhotos ) AS PhotosByCountry,
COUNT( temp.Land ) AS EventsByCountry,
rContinent,
temp.Land AS rCountry
FROM (
SELECT e.country AS Land,
COUNT( p.id ) AS allPhotos,
c.continent AS rContinent
FROM `photos` p
INNER JOIN `events` e ON e.id = p.eventID
INNER JOIN countries c ON e.country = c.country
GROUP BY p.eventID
)temp
GROUP BY rCountry
ORDER BY rContinent, rCountry";
return DB::select($rawQuery);
}
如果将来需要调整某些内容(索引可能在某个阶段),这对 SQL 用户来说很有效并且很容易理解。
无论如何,谢谢你的努力,我不会再问 Eloquent 问题了,而是用原生查询来代替。