0

我有一张这样的桌子:

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 where (param_id = 44 AND param_value=google) AND (param_id= 45 AND param_value = adTest) 。所以上面的 where 子句应该只给出 user_id = 1 而不是 user_id = 2 。他们都有 google 在 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 (?,?)
4

3 回答 3

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
于 2013-10-11T20:26:12.747 回答
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 在这里有一个很好的答案:如何过滤 SQL 结果中的多通关系,有很多方法可以编写这样的查询,以及与性能测试。

测试是在 Postgres 中完成的,因此一些查询甚至不在 MySQL 中运行,但至少有一半的查询确实运行,并且其中许多查询的效率相似。

于 2013-10-12T16:23:22.023 回答
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
;

有关演示,请参见http://sqlfiddle.com/#!2/17b65/4

于 2013-10-11T21:53:00.980 回答