筛选数据连接
问题描述:
我有一些简单的数据:筛选数据连接
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 |
+----+
答
既然你需要找到一个任务与参数值modem
和printer
,有必要加入表tbl_parameter
和tbl_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%'
如果你想测试,如果参数值正好等于modem
和printer
,你可以更换WHERE
子句:
WHERE tpv1.value = 'modem' AND tpv2.value = 'printer'
注意:如果您使用LEFT JOIN
代替INNER JOIN
,查询将始终从tbl_task
返回所有id
值。这显然不是预期的结果。
阅读documentation about the JOIN syntax了解更多信息。
哇!我以前从未见过两次加入。我无法理解它甚至是如何工作的。但它很好用,谢谢!顺便说一下,如果我只需要任务数据,那么使用何种类型的JOIN无关紧要? – Exerion
阅读我的(编辑)答案的底部。 – Jocelyn