中间表进行多值搜索

时间:2017-12-27 12:02:11

标签: mysql sql many-to-many

我有这些免费表格:

Record
+--+----------+
|id|created_at|
+--+----------+
|1 |2017-12-26|
+--+----------+
|2 |2017-12-27|
+--+----------+

Parameters
+--+----------+
|id|field_name|
+--+----------+
|1 |First name|
+--+----------+
|2 |Last name |
+--+----------+

Records_Parameters
+--+---------+------------+-----+
|id|record_id|parameter_id|value|
+--+---------+------------+-----+
|1 |1        |1           |John |
+--+---------+------------+-----+
|2 |1        |2           |Smith|
+--+---------+------------+-----+
|3 |2        |1           |Joe  |
+--+---------+------------+-----+
|4 |2        |2           |Smith|
+--+---------+------------+-----+

我无法弄清楚如何编写查询以按参数搜索:

例如:

1。 First name = JohnLast name = Smith我应该Record id: 1,2

2。 First name = JoeLast name = Smith我应该Record id: 2

参数计数将发生变化。

提前致谢。

已更新

我试过了:

SELECT r.id FROM Records_Parameters as rp JOIN Parameters p on (rp.parameter_id = p.id) JOIN Record r on (r.id = rp.record_id) WHERE 1 AND (rp.parameter_id = 1 and rp.value like "%John%" AND rp.parameter_id = 2 and rp.value like "%Smith%");

===

[..] WHERE 1 AND rp.parameter_id = 1 and rp.value like "%John%" AND rp.parameter_id = 2 and rp.value like "%Smith%";

===

SELECT id FROM records_params WHERE 1 AND (param_id = 1 AND value LIKE "%John%" AND param_id = 2 AND value LIKE "%Smith%");

到目前为止没有运气。

已更新

@Gordon Linoff回答原始问题,所以我将其标记为正确答案。

此外,我使用一点点不同的解决方案更新了这个问题,并更新了@Gordon Linoff查询:

SELECT rp.record_id FROM Records_Parameters rp JOIN Parameters p on rp.parameter_id = p.id WHERE (p.id = 1 AND (rp.value LIKE "%John%" OR rp.value LIKE "%Joe%")) OR (p.id = 2 AND rp.value LIKE "%Smith%") GROUP BY rp.record_id HAVING COUNT(distinct p.id) = 2;

使用此查询可以通过多个字段完成搜索,可以通过子字符串搜索值。

1 个答案:

答案 0 :(得分:1)

这是对问题的原始版本的回答。

一种方法使用group byhaving

select rp.record_id
from record_parameters rp join
     parameters p
     on rp.parameter_id = p.id
where (p.field_name, rp.value) in ( ('First name', 'John'), ('Last name', 'Smith') )
group by rp.record_id
having count(distinct p.field_name) = 2;