数据库
首页 > 数据库> > mysql-如何在LEFT JOIN上使用LIMIT?

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

作者:互联网

我有2个称为类别和产品的表,具有这种关系:

category.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雄辩地说,我可以使用这样的东西:

$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表中获得了前两行,然后尝试从类别向那两行进行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小提琴.

在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小提琴.

您也可以使用以下方法:

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;

我真的不建议这样做,因为相关子查询的性能通常比按顺序排序要差得多.但是,如果每个类别的产品没有太多,那么就可以了(使用正确的索引).

标签:eloquent,orm,relational-database,mariadb,mysql
来源: https://codeday.me/bug/20191108/2007241.html