过滤两个左连接的数据

时间:2017-04-11 08:48:39

标签: mysql left-join where

我有一些简化数据:

mysql> SELECT * FROM tbl_task;
+----+----------+
| id | data     |
+----+----------+
|  1 | data 1   |
|  2 | data 2   |
|  3 | data 3   |
|  4 | data 4   |
|  5 | data 55  |
|  6 | data 166 |
+----+----------+

mysql> SELECT * FROM tbl_parameter;
+----+---------+----------+
| id | task_id | name     |
+----+---------+----------+
|  1 |       1 | hardware |
|  2 |       1 | hardware |
|  3 |       1 | hardware |
|  4 |       2 | hardware |
|  5 |       2 | hardware |
|  6 |       3 | hardware |
|  7 |       3 | hardware |
|  8 |       3 | hardware |
|  9 |       4 | hardware |
| 10 |       5 | hardware |
| 11 |       5 | hardware |
| 12 |       5 | hardware |
| 13 |       6 | hardware |
| 14 |       6 | hardware |
+----+---------+----------+

mysql> SELECT * FROM tbl_parameter_value;
+----+--------------+---------+
| id | parameter_id | value   |
+----+--------------+---------+
|  1 |            1 | modem   |
|  2 |            2 | printer |
|  3 |            3 | 220     |
|  4 |            4 | 24      |
|  5 |            5 | modem   |
|  6 |            6 | printer |
|  7 |            7 | 220     |
|  8 |            8 | gps     |
|  9 |            9 | 24      |
| 10 |           10 | printer |
| 11 |           11 | modem   |
| 12 |           12 | 220     |
| 13 |           13 | 24      |
| 14 |           14 | modem   |
+----+--------------+---------+

因此,任务有多个参数,每个参数都有一个值。它似乎没有意义,但这只是简化的数据。

我使用两个联接来获取value数据:

mysql> SELECT tbl_task.id, tbl_parameter_value.value
    -> FROM tbl_task
    -> LEFT JOIN tbl_parameter ON tbl_task.id = tbl_parameter.task_id
    -> LEFT JOIN tbl_parameter_value ON tbl_parameter.id = tbl_parameter_value.parameter_id;
+----+---------+
| id | value   |
+----+---------+
|  1 | modem   |
|  1 | printer |
|  1 | 220     |
|  2 | 24      |
|  2 | modem   |
|  3 | printer |
|  3 | 220     |
|  3 | gps     |
|  4 | 24      |
|  5 | printer |
|  5 | modem   |
|  5 | 220     |
|  6 | 24      |
|  6 | modem   |
+----+---------+

如您所见,task.id列中有一些重复项。我需要的是过滤此查询以同时仅返回参数值为modem AND printer的任务。

以下查询显然没有任何意义:

SELECT tbl_task.id, tbl_parameter_value.value
FROM tbl_task
LEFT JOIN tbl_parameter ON tbl_task.id = tbl_parameter.task_id
LEFT JOIN tbl_parameter_value ON tbl_parameter.id = tbl_parameter_value.parameter_id
WHERE value LIKE '%modem%' AND value LIKE '%printer%'

我也试过了:

SELECT tbl_task.id, tbl_parameter_value.value
FROM tbl_task
LEFT JOIN tbl_parameter ON tbl_task.id = tbl_parameter.task_id
LEFT JOIN tbl_parameter_value ON tbl_parameter.id = tbl_parameter_value.parameter_id AND tbl_parameter_value.value LIKE '%modem%' OR tbl_parameter_value.value LIKE '%printer%'

它给出了错误的结果。

如何同时使用参数值调制解调器和打印机过滤不同的任务? 根据这些数据我需要得到的是:

+----+
| id |
+----+
|  1 |
|  5 |
+----+

1 个答案:

答案 0 :(得分:1)

由于您需要查找参数值为modem AND printer的任务,因此需要加入表格tbl_parametertbl_parameter_value查询中两次(使用表别名):

SELECT t.id
FROM tbl_task t
INNER JOIN tbl_parameter tp1 ON t.id = tp1.task_id
INNER JOIN tbl_parameter tp2 ON t.id = tp2.task_id
INNER JOIN tbl_parameter_value tpv1 ON tp1.id = tpv1.parameter_id
INNER JOIN tbl_parameter_value tpv2 ON tp2.id = tpv2.parameter_id
WHERE tpv1.value LIKE '%modem%' AND tpv2.value LIKE '%printer%'

如果您想测试参数值是否完全等于modemprinter,您可以将WHERE子句替换为:

WHERE tpv1.value = 'modem' AND tpv2.value = 'printer'

注意:如果您使用LEFT JOIN代替INNER JOIN,则查询将始终返回id的所有tbl_task值。这显然不是预期的结果。

阅读documentation about the JOIN syntax了解详情。