繁体   English   中英

如何选择两行应匹配的不同行?

[英]How to select distinct rows where 2 columns should match on multiple rows?

我有这样一张桌子:

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_id,其中(param_id = 44 AND param_value = google)和(param_id = 45 AND param_value = adTest)。 因此,上述where子句应仅提供user_id = 1而不是user_id = 2。 他们都在param_id 44上拥有google,但只有用户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 (?,?)
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

其他方式:

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' ;

如果对(user_id, param_id)UNIQUE约束,则不需要DISTINCT

为了提高效率,请在(param_id, param_value, user_id)上添加索引


您正在处理的问题称为“关系部门”,@ Erwin Brandstetter在此处提供了一个很好的答案: 如何使用has- man -through关系过滤SQL结果 ,并使用多种方式编写这样的查询与性能测试。

测试是在Postgres中完成的,因此有些查询甚至没有在MySQL中运行,但至少有一半可以运行,并且效率在许多查询中都差不多。

如果要进行优化,则不需要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进行演示

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM