合并来自三个不相关表

时间:2018-03-07 20:47:41

标签: mysql sql join

我需要使用数据可视化工具,该工具只能查询给定图表的单个来源。我有三个表,我需要可视化的数据。所以,我需要将它们组合成一个视图或输出表。以下是表格模式:

MySQL [bdCaloriesNeeded]> desc activity;
+---------------+----------+------+-----+---------+-------+
| Field         | Type     | Null | Key | Default | Extra |
+---------------+----------+------+-----+---------+-------+
| id            | int(11)  | YES  |     | NULL    |       |
| name          | text     | YES  |     | NULL    |       |
| Gender        | text     | YES  |     | NULL    |       |
| age           | int(11)  | YES  |     | NULL    |       |
| length        | text     | YES  |     | NULL    |       |
| weight        | int(11)  | YES  |     | NULL    |       |
| exercise      | int(11)  | YES  |     | NULL    |       |
| food_consumed | int(11)  | YES  |     | NULL    |       |
| date          | datetime | YES  |     | NULL    |       |
+---------------+----------+------+-----+---------+-------+

MySQL [bdCaloriesNeeded]> desc exercise;
+---------------------+---------+------+-----+---------+-------+
| Field               | Type    | Null | Key | Default | Extra |
+---------------------+---------+------+-----+---------+-------+
| Gender              | text    | YES  |     | NULL    |       |
| Min_Age             | int(11) | YES  |     | NULL    |       |
| Max_Age             | int(11) | YES  |     | NULL    |       |
| min_exercise_hours  | int(11) | YES  |     | NULL    |       |
| med_exercise_hours  | int(11) | YES  |     | NULL    |       |
| high_exercise_hours | int(11) | YES  |     | NULL    |       |
+---------------------+---------+------+-----+---------+-------+

MySQL [bdCaloriesNeeded]> desc food;
+---------------------+---------+------+-----+---------+-------+
| Field               | Type    | Null | Key | Default | Extra |
+---------------------+---------+------+-----+---------+-------+
| size                | text    | YES  |     | NULL    |       |
| min_pounds          | int(11) | YES  |     | NULL    |       |
| max_pounds          | int(11) | YES  |     | NULL    |       |
| min_food_oz_per_day | int(11) | YES  |     | NULL    |       |
| max_food_oz_per_day | int(11) | YES  |     | NULL    |       |
+---------------------+---------+------+-----+---------+-------+

这里是上表中的实际源数据:

MySQL [bdCaloriesNeeded]> select * from activity;
+------+----------+--------+------+--------+--------+----------+---------------+---------------------+
| id   | name     | Gender | age  | length | weight | exercise | food_consumed | date                |
+------+----------+--------+------+--------+--------+----------+---------------+---------------------+
|   14 | spot     | M      |    2 | 2'7"   |     13 |        5 |            13 | 2017-10-08 00:00:00 |
|   67 | princess | F      |    6 | 3'3"   |     75 |        3 |            15 | 2017-09-05 00:00:00 |
+------+----------+--------+------+--------+--------+----------+---------------+---------------------+

MySQL [bdCaloriesNeeded]> select * from exercise
+--------+---------+---------+--------------------+--------------------+---------------------+
| Gender | Min_Age | Max_Age | min_exercise_hours | med_exercise_hours | high_exercise_hours |
+--------+---------+---------+--------------------+--------------------+---------------------+
| M      |       1 |       2 |                  1 |                  4 |                   6 |
| M      |       3 |       7 |                  1 |                  3 |                   4 |
| M      |       8 |      15 |                  1 |                  2 |                   2 |
| F      |       1 |       2 |                  1 |                  4 |                   6 |
| F      |       3 |       7 |                  1 |                  3 |                   5 |
| F      |       8 |      15 |                  1 |                  2 |                   2 |
+--------+---------+---------+--------------------+--------------------+---------------------+

MySQL [bdCaloriesNeeded]> select * from food;
+--------+------------+------------+---------------------+---------------------+
| size   | min_pounds | max_pounds | min_food_oz_per_day | max_food_oz_per_day |
+--------+------------+------------+---------------------+---------------------+
| small  |          1 |         10 |                  12 |                  18 |
| medium |         11 |         30 |                  15 |                  30 |
| large  |         31 |        100 |                  25 |                  50 |
+--------+------------+------------+---------------------+---------------------+

这是我执行的SQL:

SELECT activity.id, activity.name, activity.Gender, activity.age, activity.weight, activity.exercise, activity.date, exercise.min_exercise_hours, exercise.high_exercise_hours, food.size, food.min_food_oz_per_day, food.max_food_oz_per_day
from activity, exercise, food
where (
activity.exercise between exercise.min_exercise_hours and exercise.high_exercise_hours
)
and
(
activity.weight between food.min_pounds and food.max_pounds
)
and
(
activity.Gender = exercise.Gender
)

以下是不受欢迎的结果:

+------+----------+--------+------+--------+----------+---------------------+--------------------+---------------------+--------+---------------------+---------------------+
| id   | name     | Gender | age  | weight | exercise | date                | min_exercise_hours | high_exercise_hours | size   | min_food_oz_per_day | max_food_oz_per_day |
+------+----------+--------+------+--------+----------+---------------------+--------------------+---------------------+--------+---------------------+---------------------+
|   14 | spot     | M      |    2 |     13 |        5 | 2017-10-08 00:00:00 |                  1 |                   6 | medium |                  15 |                  30 |
|   67 | princess | F      |    6 |     75 |        3 | 2017-09-05 00:00:00 |                  1 |                   6 | large  |                  25 |                  50 |
|   67 | princess | F      |    6 |     75 |        3 | 2017-09-05 00:00:00 |                  1 |                   5 | large  |                  25 |                  50 |
+------+----------+--------+------+--------+----------+---------------------+--------------------+---------------------+--------+---------------------+---------------------+

我为公主买了两排。每只狗需要一排。所需的结果应该使用公主的体重来每天查找正确的食物范围,并使用她的性别和年龄来查找正确的运动范围。

我已经敲了好几个小时,不知道这里有什么问题。

1 个答案:

答案 0 :(得分:0)

有趣的是,你的问题表明这些表是无关的,但它们实际上是相关的,这是关系数据库的重点,基于这些关系来连接数据。

问题在于,您的锻炼表仅在运动时间使用锻炼表中的公主匹配第4行和第5行进行连接。 (第一个where子句也匹配第1行和第2行,但后面的where子句限制了Gender)

在我看来,您还应该将锻炼表上的匹配限制为年龄以及exercisegender

所以添加

and (activity.age between exercise.min_age and exercise.max_age) 

另外,我个人喜欢使用JOIN子句而不是WHERE - 它将所有内容保存在一起。

SELECT activity.id,
       activity.name,
       activity.Gender,
       activity.age,
       activity.weight,
       activity.exercise,
       activity.date,
       exercise.min_exercise_hours,
       exercise.high_exercise_hours,
       food.size,
       food.min_food_oz_per_day,
       food.max_food_oz_per_day
FROM activity
  JOIN exercise
    ON activity.exercise BETWEEN exercise.min_exercise_hours AND exercise.high_exercise_hours 
   AND activity.Gender = exercise.Gender
   AND activity.age BETWEEN exercise.min_age AND exercise.max_age
  JOIN food
    ON activity.weight BETWEEN food.min_pounds AND food.max_pounds

由于您正在寻找可能超出建议范围的内容,您可能需要考虑在锻炼和食物表上进行LEFT JOIN,以便活动桌上不在任何范围内的狗仍会出现(对于另一个表的缺失数据,使用NULL值。) 只需将连接线更改为LEFT JOIN,如下所示:

LEFT JOIN exercise
LEFT JOIN food

另请参阅:What is the difference between "INNER JOIN" and "OUTER JOIN"?