从 table 获取多行到另一个 table 的每行
Get multiple rows from a table to per row of another table
我这里有一个问题,我想知道是否可以在一次查询中执行此操作,而不是让服务器执行多次查询。
事情是这样的,我想要的是,在每个类别中,在 24 家商店的限制内搜索属于该类别的所有商店。也就是说,假设我注册了5个类别,我将搜索属于该类别的24家商店,最终我将在查询结果中总共有120家商店。
以下代码是示例,但这只会获取任何类别的前 24 家商店,而不会遍历每个类别。
SELECT *
FROM categories c
LEFT JOIN (SELECT * FROM stores_categories LIMIT 24 OFFSET 0) sc ON sc.id_category = c.id
WHERE type = 'STORE' OR type = 'ALL';
有人发给我这个,它与我的问题非常相似,How to SELECT the newest four items per category?,有点像,但我希望能够限制并使用偏移量来制作页面,而不仅仅是每个类别中最近的前 24 个。
示例代码来自 link 我得到的:
SELECT sc1.*
FROM stores_categories sc1
LEFT OUTER JOIN stores_categories sc2 ON (sc1.id_category = sc2.id_category AND sc1.id_store < sc2.id_store)
GROUP BY sc1.id_store
HAVING COUNT(*) < 24
ORDER BY sc1.id_category;
而我的数据库服务器是5.5.64-MariaDB版本。一个 fiddle 示例,可以使用我的数据库中的相同值进行测试。 https://www.db-fiddle.com/f/jcowJL9S4FQXqKg2yMa8kf/0
它可以使用每个类别的计算 row_number。
--
-- Emulated row_number via variables
--
SELECT sc.id, id_store
, cat.name AS cat_name
, cat.type AS cat_type
, rn
FROM
(
SELECT sc.*
, @rn := CASE
WHEN @cat_id = sc.id_category
THEN @rn + 1 ELSE 1
END AS rn
, @cat_id := sc.id_category as cat_id
FROM stores_categories sc
CROSS JOIN (SELECT @cat_id:=0, @rn:=0) vars
ORDER BY sc.id_category, sc.id_store DESC, sc.id DESC
) sc
LEFT JOIN categories cat
ON cat.id = sc.id_category
WHERE rn BETWEEN 1 AND 24
ORDER BY sc.id_category, sc.id_store DESC, sc.id DESC
或
--
-- Grouped self-join
--
SELECT sc.id, sc.id_store
, cat.name AS cat_name
, cat.type AS cat_type
, COUNT(sc2.id_store) AS cnt
FROM stores_categories sc
LEFT JOIN stores_categories sc2
ON sc2.id_category = sc.id_category
AND sc2.id_store >= sc.id_store
LEFT JOIN categories cat
ON cat.id = sc.id_category
GROUP BY sc.id
HAVING cnt BETWEEN 1 AND 24
ORDER BY sc.id_category, sc.id_store DESC;
或
--
-- Correlated sub-query
--
SELECT sc.id, id_store
, cat.name AS cat_name
, cat.type AS cat_type
, ( select count(*)
from stores_categories sc2
where sc2.id_category = sc.id_category
and sc2.id_store >= sc.id_store
) as rn
FROM stores_categories AS sc
LEFT JOIN categories cat
ON cat.id = sc.id_category
HAVING rn BETWEEN 1 AND 24
ORDER BY sc.id_category, sc.id_store DESC;
演示 db<>fiddle here
我这里有一个问题,我想知道是否可以在一次查询中执行此操作,而不是让服务器执行多次查询。
事情是这样的,我想要的是,在每个类别中,在 24 家商店的限制内搜索属于该类别的所有商店。也就是说,假设我注册了5个类别,我将搜索属于该类别的24家商店,最终我将在查询结果中总共有120家商店。
以下代码是示例,但这只会获取任何类别的前 24 家商店,而不会遍历每个类别。
SELECT *
FROM categories c
LEFT JOIN (SELECT * FROM stores_categories LIMIT 24 OFFSET 0) sc ON sc.id_category = c.id
WHERE type = 'STORE' OR type = 'ALL';
有人发给我这个,它与我的问题非常相似,How to SELECT the newest four items per category?,有点像,但我希望能够限制并使用偏移量来制作页面,而不仅仅是每个类别中最近的前 24 个。
示例代码来自 link 我得到的:
SELECT sc1.*
FROM stores_categories sc1
LEFT OUTER JOIN stores_categories sc2 ON (sc1.id_category = sc2.id_category AND sc1.id_store < sc2.id_store)
GROUP BY sc1.id_store
HAVING COUNT(*) < 24
ORDER BY sc1.id_category;
而我的数据库服务器是5.5.64-MariaDB版本。一个 fiddle 示例,可以使用我的数据库中的相同值进行测试。 https://www.db-fiddle.com/f/jcowJL9S4FQXqKg2yMa8kf/0
它可以使用每个类别的计算 row_number。
--
-- Emulated row_number via variables
--
SELECT sc.id, id_store
, cat.name AS cat_name
, cat.type AS cat_type
, rn
FROM
(
SELECT sc.*
, @rn := CASE
WHEN @cat_id = sc.id_category
THEN @rn + 1 ELSE 1
END AS rn
, @cat_id := sc.id_category as cat_id
FROM stores_categories sc
CROSS JOIN (SELECT @cat_id:=0, @rn:=0) vars
ORDER BY sc.id_category, sc.id_store DESC, sc.id DESC
) sc
LEFT JOIN categories cat
ON cat.id = sc.id_category
WHERE rn BETWEEN 1 AND 24
ORDER BY sc.id_category, sc.id_store DESC, sc.id DESC
或
--
-- Grouped self-join
--
SELECT sc.id, sc.id_store
, cat.name AS cat_name
, cat.type AS cat_type
, COUNT(sc2.id_store) AS cnt
FROM stores_categories sc
LEFT JOIN stores_categories sc2
ON sc2.id_category = sc.id_category
AND sc2.id_store >= sc.id_store
LEFT JOIN categories cat
ON cat.id = sc.id_category
GROUP BY sc.id
HAVING cnt BETWEEN 1 AND 24
ORDER BY sc.id_category, sc.id_store DESC;
或
--
-- Correlated sub-query
--
SELECT sc.id, id_store
, cat.name AS cat_name
, cat.type AS cat_type
, ( select count(*)
from stores_categories sc2
where sc2.id_category = sc.id_category
and sc2.id_store >= sc.id_store
) as rn
FROM stores_categories AS sc
LEFT JOIN categories cat
ON cat.id = sc.id_category
HAVING rn BETWEEN 1 AND 24
ORDER BY sc.id_category, sc.id_store DESC;
演示 db<>fiddle here