我看了lot个试图解决这个问题的问题,最后得到了一个符合我想要的问题。但我想知道是否有更好的方法来做到这一点?基本上,由于belongs_to关系,我有一堆表连接在一起,我希望返回的行数只能与其中一个belongs_to表中的最大行数一样多。
由于这是一种笨拙的措辞,这是一个例子。说我有2个食谱,每个都有步骤和一些营养。配方1有3个步骤和3个营养,配方2有2个步骤和4个营养。对于配方1,最多应返回3行,对于配方2,最多应返回4行。这是数据的小提琴:http://sqlfiddle.com/#!9/bcce59/2
如果小提琴由于某种原因不起作用,这里是表格模式:
CREATE TABLE recipe
(`id` int PRIMARY KEY, `title` varchar(64))
;
CREATE TABLE step
(`rid` int, `instruction` varchar(64),
FOREIGN KEY(rid) REFERENCES recipe(id) )
;
CREATE TABLE nutrition
(`rid` int, `name` varchar(64), `amount` int,
FOREIGN KEY(rid) REFERENCES recipe(id) )
;
以下是一些示例数据:
INSERT INTO recipe
(`id`, `title`)
VALUES
(1, 'Cookies'),
(2, 'Bananas')
;
INSERt INTO step
(`rid`, `instruction`)
VALUES
(1, 'Unwrap'),
(1, 'Dip in milk'),
(1, 'Eat'),
(2, 'Peal'),
(2, 'Eat')
;
INSERT INTO nutrition
(`rid`, `name`, `amount`)
VALUES
(1, 'calories', 120),
(1, 'sugar', 300),
(1, 'fat', 50),
(2, 'calories', 50),
(2, 'sugar', 50),
(2, 'fat', 20),
(2, 'carb', 30)
;
现在,我想我最初可能会和小组一起做这件事。但是像
这样的东西SELECT id, title, instruction, name, amount FROM
recipe
LEFT JOIN step ON recipe.id = step.rid
LEFT JOIN nutrition on recipe.id = nutrition.rid
GROUP BY id, instruction, name, amount;
将返回17行,因为它是一个产品,并且按列分组的唯一配对数对于配方1为9,对于配方2为8.这样就可以了。在标签之间进行了大量搜索并倾注了MySQL文档和我所拥有的食谱书之后,我想出了以下查询来完成这项工作:
SELECT id, title, instruction, name, amount FROM
(
SELECT
id,
title,
instruction,
name,
amount
FROM recipe
LEFT JOIN step ON recipe.id = step.rid
LEFT JOIN nutrition on recipe.id = nutrition.rid
) data
INNER JOIN
(
SELECT
s.rid,
CASE
WHEN
GREATEST(numSteps, numNutrition) = numSteps
THEN instruction
WHEN
GREATEST(numSteps, numNutrition) = numNutrition
THEN name
END as row
FROM
(
SELECT
rid,
instruction
FROM step GROUP BY rid, instruction
) s
LEFT JOIN
(
SELECT
rid,
name
FROM nutrition GROUP BY rid, name
) n
ON s.rid = n.rid
LEFT JOIN
(
SELECT rid, COUNT(*) as numNutrition
FROM nutrition GROUP BY rid
) nSum
ON n.rid = nSum.rid
LEFT JOIN
(
SELECT rid, COUNT(*) as numSteps
FROM step GROUP BY rid
) sSum
ON s.rid = sSum.rid
GROUP by rid, row
) biggest
ON data.id = biggest.rid
GROUP BY data.id, biggest.row
;
然而,将我的宝贝2个belongs_to表的例子推广到我的实际数据库,其中有超过20个表加入,这让我很担心。当使用天真的连接方法时,我的真实数据每个'recipe'有15k到90k行,所以我关心查询的性能以及我可能只是缺少一些非常基本和简单的东西来帮助解决这个问题。我真的不想写一个存储过程来做这个,虽然我想知道一个视图表是否有意义?我的问题是
为奇怪的问题标题道歉,我不知道如何简洁地说出我正在对此查询做什么。
我意识到我的小提琴没有产生正确的数据,所以这里是一个编辑,以明确查询的最终结果集应该是什么:
+----+---------+-------------+----------+--------+
| id | title | instruction | name | amount |
+----+---------+-------------+----------+--------+
| 1 | Cookies | Unwrap | calories | 120 |
| 1 | Cookies | Dip in milk | sugar | 300 |
| 1 | Cookies | Eat | fat | 50 |
| 2 | Bananas | Peel | calories | 50 |
| 2 | Bananas | Peel | sugar | 50 |
| 2 | Bananas | Eat | fat | 20 |
| 2 | Bananas | Eat | carb | 30 |
+----+---------+-------------+----------+--------+
7 rows in set (0.00 sec)
这样的事情,每个指令/营养价值在结果集中至少出现一次。对于那些与其他belongs_to表相比没有最大行数的列,允许重复。