【问题标题】:Complex query 3 tables with 2 INNER JOIN, 1 subquery, 2 Group By in Laravel在 Laravel 中复杂查询 3 个表,其中 2 个 INNER JOIN、1 个子查询、2 个 Group By
【发布时间】:2015-05-13 02:30:26
【问题描述】:

这是我在 Laravel 中创建复杂查询的最后一次尝试。在这种情况下,我需要 3 个表:photos, events, countries。每个活动都有很多或没有照片,每个国家可能有多个带照片的活动。 我的结果显示

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

谁能帮我把它翻译成没有DB::raw()whereRaw() 的Laravel Query builder。我构建那个东西的主要问题是子查询。

我得到了所有表的ModelsPhoto, 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

【问题讨论】:

  • 我认为没有 DB::Raw 是不可能的。在这个 SO question 中,他们提供了一个如何从子选择中进行选择的答案。 stackoverflow.com/questions/24823915/…
  • Laravel 5 有这方面的功能吗?一定是常见问题...
  • 这是一篇有趣的文章。考虑到 Eloquent Query Builder 应该让我们的事情变得更容易,那里的有效答案可以做除此之外的所有事情。
  • ORM 只会让查询更容易,因为它是为它构建的。通常这相当于所有查询的 90%(疯狂猜测)。对于更花哨的东西,你总是可以做一个原始查询。我在 Laravel 项目中也使用了它,但我可以通过更改表格设计来使其更容易。
  • 你能发布表格吗,也许 2 个简单的查询也可以做到?

标签: mysql laravel laravel-4 eloquent query-builder


【解决方案1】:

试试这个:

国家模式

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 查询与计数)。但我认为这是一种很好的计数方式。

【讨论】:

  • eventsCount() 不能这样工作,因为(如最初问题中所述)并非每个活动都有照片。也许我应该在测试数据中添加一个没有照片的事件。 photoCount(),好吧,我太累了,现在无法分析和测试它:-),但这实际上可以工作。
  • Blablabla...感谢您付出的巨大努力。但与此同时,我已经根据初始查询产生的结果构建了我的页面加载和 AJAX 请求。翻译您的代码以将我的结果(可能有效)转换为我的页面太复杂了,除非我以上述问题中的格式获得结果。我为你的努力点赞! :-) 但我现在需要继续相关工作。
  • 好的,没问题。我自己对此很感兴趣。
【解决方案2】:

完成问题:

由于在 Eloquent Query Builder 中构建我的初始查询似乎不可能或太复杂,我在我的 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);   
}

如果将来需要调整某些东西(索引可能在某个阶段),这对 SQLers 来说很有效并且很容易理解。

无论如何,感谢您的努力,我不会再问 Eloquent 问题,而是使用原生查询。

【讨论】:

  • 不是我真正想要的解决方案,但显然是最简单的方法。
猜你喜欢
  • 2016-07-04
  • 1970-01-01
  • 2018-04-03
  • 1970-01-01
  • 1970-01-01
  • 2014-12-27
  • 2014-02-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多