SQL - 在不使用UNION

时间:2017-12-14 16:14:24

标签: mysql

我有桌子:

meal_categories
---------------------------
category_id | category_name
1           | Hot Drinks
2           | Cold Drinks
3           | Alcohol Drinks


meals
---------------------------------
meal_id | category_id | meal_name
1       | 1           | Tea
2       | 2           | Sprite
3       | 3           | Vodka + Sprite


meals_to_meals
------------------------
meal_id | mapped_meal_id
3       | 2

如您所见,任何一餐都可以包含任意数量的其他餐点(来自相同/其他类别)。

我们要说我需要显示第3次餐( Vodka + Sprite )的类别以及任何子类别(以及其中的用餐次数)如果有饭的话。所以结果应该是:

category_name  | total_meals
Alcohol Drinks | 1
Cold Drinks    | 1

如果有人对这些数字意味着什么感到困惑:第3次餐是属于酒精饮料本身,所以我们有1和第3次餐还有1餐从Cold Drinks类别在里面,所以我希望计算有意义。

对我来说,最大的挑战是选择分餐作为单独的行。如果我使用JOIN查询,它将只返回一行(即使它正确返回映射的膳食ID):

SELECT * FROM meals 
JOIN meals_to_meals
ON meals.meal_id=meals_to_meals.meal_id AND meals.meal_id=3

因此经过大量搜索后我决定使用UNION:

SELECT aaa.* FROM meals as aaa
JOIN meals_to_meals
ON aaa.meal_id=meals_to_meals.meal_id
GROUP BY aaa.meal_id
UNION ALL
SELECT meals.* FROM meals_to_meals
JOIN meals
ON meals_to_meals.mapped_meal_id=meals.meal_id

这个正确地返回饭菜+映射的饭菜(作为单独的行),但如果我添加进一步的查询以显示其中的类别和用餐数量,我会收到错误使用的SELECT语句具有不同的列数< /强>

如果我能够在不使用UNION的情况下获得相同的结果,我确信我可以以某种方式设法显示类别(因此我更容易理解查询)。有什么想法吗?

顺便说一下,这里是小提琴,随意玩它 - http://sqlfiddle.com/#!9/64313b/8

1 个答案:

答案 0 :(得分:1)

UNION ALL已经是最好的方法了,只要这只是两个级别(饮料可以包含其他饮料,但饮料不能包含其他饮料本身由其他饮料组成 - 您为此而且# 39; d需要一个MySQL没有特色的递归查询。

以下是用餐3的查询:

select mc.category_name, count(*) as total_meals
from
(
  select category_id from meals where meal_id = 3
  union all
  select category_id from meals where meal_id in
    (select mapped_meal_id from meals_to_meals where meal_id = 3)
) c
join meal_categories mc using (category_id)
group by mc.category_name
order by mc.category_name;

SQL小提琴:http://sqlfiddle.com/#!9/64313b/12