我有一张这样的表:
id | user_id | param_id | param_value
1 1 44 google
2 1 45 adTest
3 1 46 Campaign
4 1 47 null
5 1 48 null
6 2 44 google
7 2 45 adAnotherTest
8 2 46 Campaign2
9 2 47 null
10 2 48 null
我想获取所有user_ids,其中(param_id = 44 AND param_value = google)AND(param_id = 45 AND param_value = adTest)。所以上面的where子句应该只给出user_id = 1而不是user_id = 2。他们都在param_id 44谷歌,但只有用户1在param_id = 45时有param_value adTest。
问题在于未来可以添加更多的参数。我需要找到一个动态查询。在这里我尝试过:
SELECT DISTINCT up.user_id FROM user_params AS up
LEFT JOIN user_params AS upp ON up.id = upp.id
WHERE up.param_id IN (?,?)
AND upp.param_value IN (?,?)
答案 0 :(得分:3)
SELECT DISTINCT up.user_id
FROM user_params AS up
LEFT JOIN user_params AS upp ON up.id = upp.id
group by up.user_id
having sum(param_id = 44 AND param_value = 'google') >= 1
and sum(param_id = 45 AND param_value = 'adTest') >= 1
答案 1 :(得分:2)
另一种方式:
SELECT -- DISTINCT
up1.user_id
FROM
user_params AS up1
JOIN
user_params AS up2
ON up1.user_id = up2.user_id
WHERE
up1.param_id = 44 AND up1.param_value = 'google'
AND
up2.param_id = 45 AND up2.param_value = 'adTest' ;
如果DISTINCT
上存在UNIQUE
约束,则您不需要(user_id, param_id)
为提高效率,请在(param_id, param_value, user_id)
你正在处理的问题被称为“关系部门”,@ Erwin Brandstetter在这里有一个很好的答案: How to filter SQL results in a has-many-through relation ,有很多方法可以编写这样的查询,以及性能测试。
测试是在Postgres完成的,因此有些查询甚至不在MySQL中运行,但至少有一半的查询运行,并且其中许多查询的效率相似。
答案 2 :(得分:0)
如果你想优化它,应该给出相同的结果,而不需要LEFT JOIN表扫描(感谢juergen d有部分)
SELECT
user_id
FROM
user_params
WHERE
param_id IN(44, 45)
AND
param_value IN('google', 'adTest')
GROUP BY
user_id
HAVING
sum(param_id = 44 AND param_value = 'google') >= 1
AND
sum(param_id = 45 AND param_value = 'adTest') >= 1
;