gpt4 book ai didi

mysql - 如何在 LEFT JOIN 上使用 LIMIT?

转载 作者:可可西里 更新时间:2023-11-01 08:08:49 26 4
gpt4 key购买 nike

我有 2 个名为 categoriesproducts 的表,具有以下关系:

categories.category_id = products.product_category_id

我想显示所有类别中的 2 个产品!

[
[category 1] =>
[
'category_id' => 1,
'category_title' => 'category_title 1',
[products] => [
'0' => [
'product_category_id' => 1,
'product_id' => 51,
'product_title' => 'product_title 1',
],
'1' => [
'product_category_id' => 1,
'product_id' => 55,
'product_title' => 'product_title 2',
]
]
],
[category 2] =>
[
'category_id' => 2,
'category_title' => 'category_title 2',
[products] => [
'0' => [
'product_category_id' => 2,
'product_id' => 32,
'product_title' => 'product_title 3',
],
'1' => [
'product_category_id' => 2,
'product_id' => 33,
'product_title' => 'product_title 4',
]
]
],
...
]

我 Laravel Eloquent 我可以使用这样的东西:

$categories = Category::with(['products' => function($q) {
$q->limit(2)
}])->get();

但我没有使用 Laravel,我需要纯 SQL 代码!我试过这段代码:

SELECT
CT.category_id,
PT.product_category_id,
CT.category_title,
PT.product_id,
PT.product_title
FROM
categories CT
LEFT JOIN(
SELECT
*
FROM
products
LIMIT 2
) AS PT
ON
CT.category_id = PT.product_category_id
WHERE
CT.category_lang = 'en'

但是这段代码有问题!似乎 MYSQL 首先在 products 表中获取前 2 行,然后尝试从 categories 到那 2 行的 LEFT JOIN!这会导致返回产品的 null 值(如果我删除 LIMIT 效果很好,但我需要 LIMIT)

我也测试过这段代码:(已更新)

SELECT
CT.category_id,
PT.product_category_id,
CT.category_title,
PT.product_id,
PT.product_title
FROM
categories CT
LEFT JOIN(
SELECT
*
FROM
products
WHERE
product_category_id = CT.category_id
LIMIT 5
) AS PT
ON
CT.category_id = PT.product_category_id
WHERE
CT.category_lang = 'en'

但是我收到了这个错误:

1054 - Unknown column 'CT.category_id' in 'where clause'

我无法在子查询中访问 CT.category_id

什么是最好的解决方案?

最佳答案

在 MySQL 中,您需要使用变量。基本思想是:

select p.*
from (select p.*,
(@rn := if(@c = product_category_id, @rn + 1,
if(@c := product_category_id, 1, 1)
)
) as rn
from (select p.*
from products p
order by p.product_category_id
) p cross join
(select @c := -1, @rn := 0) params
) p
where rn <= 2;

您可以将其用作您的子查询,然后加入其余的类别信息。

Here如果此代码有效,则为 db<>fiddle。

在 MySQL 8+/MariaDB 10.2+ 中,这更容易写成:

select p.*
from (select p.*,
row_number() over (partition by product_category_id order by product_category_id) as seqnum
from products p
) p
where seqnum <= 2;

注意:您可以通过调整两个查询中的 order by 子句来指定您想要的 2 个产品(例如,前两个按字母顺序排列)。

编辑:

在 MariaDB 10.2 中,您显然不能使用子查询进行排序,因此适当的查询是:

select p.*
from (select p.*,
(@rn := if(@c = product_category_id, @rn + 1,
if(@c := product_category_id, 1, 1)
)
) as rn
from products p cross join
(select @c := -1, @rn := 0) params
order by p.product_category_id
) p
where rn <= 2;

Here是 db<>fiddle 的。

你也可以使用这个方法:

select p.*
from products p
where (select count(*)
from products p2
where p2.product_category_id = p.product_category_id and p2.id <= p.id
) <= 2;

我真的不推荐这样做,因为相关子查询的性能通常比 order by 差很多。但是,如果每个类别的产品不是太多,那么这会很好(使用正确的索引)。

关于mysql - 如何在 LEFT JOIN 上使用 LIMIT?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53969692/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com