2016-11-21 38 views
4

我在数据库中有四个表格,即Packages,Fixtures,Deals和Fixtures Deals。如何在Laravel 5的嵌套查询中使用GroupBy?

下面是表的结构细节:

Packages: id, title 
Fixtures: id, package_id, name 
Deals: id, discound, description 
Fixtures_Deal: id, fixture_id, deal_id, price 

我需要与最低成交均价,提供在每个灯具的每个软件包相处的软件包列表。

这里是我在phpMyAdmin或SQLYog中运行的mysql查询,它工作正常,但在Laravel中,它给了我“p.title'不在GROUP BY”错误。

SELECT 
    p.title AS package_title,  
    tbl_min_value.min_price AS min_price 
FROM 
    (SELECT 
    fixture_id, 
    MIN(deal_price) AS min_price 
    FROM 
    fixture_deal 
    GROUP BY fixture_id) AS tbl_min_value 
    JOIN fixtures AS f 
    ON f.id = tbl_min_value.fixture_id 
    RIGHT JOIN packages AS p 
    ON f.package_id = p.id 
GROUP BY p.id 

顺便说一句,我想通过在模型中使用下面的方法来实现它:

return DB::statement('SELECT 
     p.title AS package_title,  
     tbl_min_value.min_price AS min_price 
    FROM 
     (SELECT 
     fixture_id, 
     MIN(deal_price) AS min_price 
     FROM 
     fixture_deal 
     GROUP BY fixture_id) AS tbl_min_value 
     JOIN fixtures AS f 
     ON f.id = tbl_min_value.fixture_id 
     RIGHT JOIN packages AS p 
     ON f.package_id = p.id 
    GROUP BY p.id'); 
+0

您是否试图以另一种方式执行它,如'$ pdo = DB :: connection() - > getPdo();'并直接启动它 – Mruf

+0

不,我没有尝试过。你能否详细说明我该怎么做?我要写这样的代码吗?: DB :: connection() - > getPdo('Query'); –

+0

https://codeshare.io/29QA72 – Mruf

回答

2

我以雄辩收集的mapWithKeys方法发现了另一种办法解决。

https://laravel.com/docs/5.3/collections#method-mapwithkeys 

因此,我分别提取了两个查询的数据,并将两个集合都映射到一个集合对象中。

示例代码:

$packages = Package::getPackages(); 

$deal_min_price = Deal::getMinimumPrice(); 

$packages_with_price = $packages->mapWithKeys(function ($packages) use ($deal_min_price) { 
    return $packages['price'] => $deal_min_price['min_price']; 
}); 

您既可以使用mapWithKey's closureforeach循环。

1

你所得到的错误是因为MySQL 5.7移动到与SQL99更柔顺。您可以阅读关于here的一些信息,但它涉及一种称为ONLY_FULL_GROUP_BY的SQL模式设置,可确保选中的所有非聚合列在GROUP BY之内。这对你的情况意味着什么?

那么,你只需添加p.titletbl_min_value.min_price以分组为它正常工作,因为他们不聚集:

GROUP BY p.id, p.title, tbl_min_value.min_price 

你可能会问,“到底为什么他们这样做? ”。那么,使用GROUP BY之前,很容易意外地“倒塌”数据,其中一行有多个可能的值可显示,所以它只显示第一个。这使您可以使用诸如MIN()MAX()之类的聚合函数来确定要显示的内容,或者将其添加到指示您希望将其分开的分组。

如果你不喜欢这种工作方式,你可以暂时这样做禁用它:

# Run this query and copy the values 
SELECT @@sql_mode; 

# Remove "ONLY_FULL_GROUP_BY" and paste it in here where the XXX is 
SET sql_mode = 'XXX'; 

或者您也可以进行改变永久通过在这样的[mysqld]部分编辑my.cnf文件,其中xxx是SELECT @@sql_mode;输出减去ONLY_FULL_GROUP_BY部分:

[mysqld] 
sql_mode=XXX 
+0

一旦我在Group By中添加其他聚合列,它不会给我一个合适的结果,这意味着它输出的结果有重复的ID,这就是问题所在。 此外,我试图修改SQL模式,但它并没有工作。 –

+0

这是因为您有多个具有相同ID的行作为您的连接结果。试试'GROUP_CONCAT(p.title)'和/或'GROUP_CONCAT(tbl_min_value.min_price)'来看看我的意思 –

+0

另外我想知道具有一个Group By列的相同查询在phpMyAdmn或SQLYog中运行良好,在Laravel 5.3中工作。所以这可能是Laravel的一个问题...不确定..! –

0

这很奇怪,一个SQL查询在phpMyAdmin工作正常,但同样没有在Laravel 5.3工作。你会发布带有示例数据的数据库结构吗,所以我们来看看?

BTW,我尝试以下SQL和Laravel 5.2是工作的罚款:

SELECT 
    p.title AS package_title,  
    tbl_min_value.min_price AS min_price 
FROM 
    (SELECT 
    fixture_id, 
    MIN(deal_price) AS min_price 
    FROM 
    fixtures_deal 
    GROUP BY fixture_id) AS tbl_min_value 
    JOIN fixtures AS f 
    ON f.id = tbl_min_value.fixture_id 
    RIGHT JOIN packages AS p 
    ON f.package_id = p.id 
GROUP BY p.id