MySQL - 连接多个映射表并计算具有不同映射条件的记录

时间:2017-11-29 12:20:18

标签: mysql join

这是我尝试编写MySQL查询的第3天。进行了大量搜索,但仍然没有按预期工作。我会尽可能地简化表格

系统有 tkr_restaurants 表:

restaurant_id | restaurant_name
1             | AA
2             | BB
3             | CC

每家餐厅都有一个部门( tkr_divisions 表):

division_id | restaurant_id | division_name
1           | 1             | AA-1
2           | 1             | AA-2
3           | 2             | BB-1

然后在 tkr_meals_to_restaurants_divisions 表中进餐,其中每餐可以被分配(映射)到整个餐馆和/或特定部门。如果用餐被映射到餐厅,所有餐厅的部门都应该看到它。如果用餐被映射到分区,则只有特定的分区才能看到它。

meal_id | mapped_restaurant_id | mapped_division_id
1       | 1                    | NULL
2       | NULL                 | 1
3       | NULL                 | 2

我需要根据用户权限显示餐馆列表和映射到它的餐馆数量。

示例1 :如果用户有权访问整个 restaurant_id 1 restaurant_3 (并且没有特定的部门),则列表应为:

AA | 3
CC | 0

(因为用户可以访问映射到餐厅1及其所有部门的餐点,以及餐厅3及其所有部门(即使餐厅3没有划分/餐食图))

示例2 :如果用户有权访问 division_id 1 ,则列表应为:

AA | 1

(因为用户只能访问映射到分区1的膳食)。

我能得到的最接近的查询是:

示例1:

    SELECT *,
    (SELECT COUNT(DISTINCT meal_id) 
    FROM 
        tkr_meals_to_restaurants_divisions 
    WHERE 
 tkr_meals_to_restaurants_divisions.mapped_restaurant_id=tkr_restaurants.restaurant_id 
    OR tkr_meals_to_restaurants_divisions.mapped_division_id=tkr_divisions.division_id)AS total_meals
    FROM 
        tkr_restaurants 
    LEFT JOIN 
        tkr_divisions 
        ON tkr_restaurants.restaurant_id=tkr_divisions.restaurant_id 
    WHERE 
        tkr_restaurants.restaurant_id IN (1, 3) 
        OR tkr_restaurants.restaurant_id IN (
            SELECT restaurant_id 
            FROM tkr_divisions 
            WHERE division_id IN (NULL)
        ) 
    GROUP BY 
       tkr_restaurants.restaurant_id 
    ORDER BY 
        tkr_restaurants.restaurant_name

然而,结果是:

AA | 2
CC | 0

我相信我的查询过于复杂,但我写的所有更简单的查询都会产生更不准确的结果。

1 个答案:

答案 0 :(得分:1)

这个查询怎么样:

SELECT 
FROM tkr_restaurants AS a 
JOIN tkr_divisions AS b 
ON a.restaurant_id = b.restaurant_id
LEFT OUTER JOIN tkr_meals_to_restaurants_divisions AS c 
ON (c.mapped_restaurant_id = a.restaurant_id OR c.mapped_division_id = b.division_id)

作为基础四你的进一步工作。它将所有信息组合到一个表中。如果您添加例如这样:

WHERE a.restaurant_id IN (1, 3)

结果将是

| restaurant_id | restaurant_name | division_id | restaurant_id | division_name | meal_id | mapped_restaurant_id | mapped_division_id |
|---------------|-----------------|-------------|---------------|---------------|---------|----------------------|--------------------|
|             1 |              AA |           1 |             1 |          AA-1 |       1 |                    1 |             (null) |
|             1 |              AA |           2 |             1 |          AA-2 |       1 |                    1 |             (null) |
|             1 |              AA |           1 |             1 |          AA-1 |       2 |               (null) |                  1 |
|             1 |              AA |           2 |             1 |          AA-2 |       3 |               (null) |                  2 |

使用COUNT(DISTINCT c.meal_id)计算不同的膳食ID,并以餐馆名称获取AA: 3作为示例2

我使用了sqlfiddle:http://sqlfiddle.com/#!9/fa2b78/18/0

<强> [编辑]

JOIN tkr_divisions AS b更改为LEFT OUTER JOIN tkr_divisions AS b

SELECT *更改为SELECT a.restaurant_name, COUNT(DISTINCT c.meal_id)

在最后添加GROUP BY a.restaurant_name

更新SQL小提琴(新链接)