MySQL选择连接表中多行的位置

标签 mysql sql group-by inner-join having

假设我有两个表,例如:

+-----------------------------+
|a                            |
+------+-----------+----------+
| a_id | firstname | lastname |
+------+-----------+----------+
|    1 | Tom       | Cruise   |
|    3 | Matt      | Damon    |
|    4 | Ben       | Affleck  |
|    8 | Ryan      | Gosling  |
+------+-----------+----------+

+-----------------------+
| b                     |
+------+------+---------+
| b_id | a_id | b_value |
+------+------+---------+
|    2 |    3 | one     |
|    1 |    3 | two     |
|    4 |    8 | three   |
|    8 |    1 | four    |
+------+------+---------+

我希望能够从 aSELECT 行,满足 b 中的一组条件,其中可能有多个行.

例如:

  • 获取 b_value 为 1 且其他 b_value 为 2 的任何人的名字和姓氏。在示例数据中,这仅指 Matt Damon。

  • 获取 b_value 为三或 b_value 为四的任何人的名字和姓氏。在示例数据中,Ryan Gosling 的 b_value 为 3,而 Tom Cruise 的 b_value 为 4,因此 Ryan Gosling 和 Tom Cruise 都将返回。

  • 获取任何人的名字和姓氏:

    • b_value 为 1,另一个 b_value 为 2。
    • b_value 为 3。

在示例数据中,Matt Damon 满足第一个条件,Ryan Gosling 满足第二个条件,因此两者都被返回。

困难来自于这些条件很复杂,组合了多个和/或条件,并且长度可变。

我目前的尝试(在本例中专门解决示例 3)是在 HAVING 中使用聚合函数:

SELECT firstname, lastname 
FROM temp_a INNER JOIN temp_b ON temp_a.a_id = temp_b.a_id 
GROUP BY temp_a.a_id 
HAVING (SUM(b_value="one") AND SUM(b_value="two")) OR SUM(b_value="three");

它得到了正确的行,但是这种方法对我来说有两个直接的问题:

  • SUM 似乎错误且复杂。我必须找到每个条件并确保每个条件都包含在 SUM 中,其中可能有很多。
  • b_value 被索引,b 有很多行。 HAVING 子句不使用索引,因此查询速度明显变慢。

我是否应该采用不同的方法来执行此类查询,请记住,我并不能真正直接控制用于过滤的条件。

最佳答案

drop table if exists a,b;
create table a( a_id int, firstname varchar(20), lastname varchar(20));
insert into a values
(    1 , 'Tom'       , 'Cruise' ),  
(    3 , 'Matt'      , 'Damon'  ),  
(    3 , 'Ben'       , 'Affleck'),  
(    8 , 'Ryan'      , 'Gosling');  

create table b( b_id int, a_id int, b_value varchar(20));
insert into b values
(    2 ,    3 , 'one'  ),   
(    1 ,    3 , 'two'  ),   
(    4 ,    8 , 'three'),   
(    8 ,    1 , 'four' );


select firstname, lastname,s.vals
from a
join
(
select b.a_id, group_concat(b_value) vals from b group by b.a_id
) s on a.a_id = s.a_id

where s.vals in ('one,two') or s.vals in ('three')

+-----------+----------+---------+
| firstname | lastname | vals    |
+-----------+----------+---------+
| Matt      | Damon    | one,two |
| Ben       | Affleck  | one,two |
| Ryan      | Gosling  | three   |
+-----------+----------+---------+
3 rows in set (0.02 sec)

关于MySQL选择连接表中多行的位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43068422/

相关文章:

c# - 已发布的 ASP.NET MVC 网站中的计时器问题

mysql - SQL - 删除较早日期的所有重复项

如果字段不相等,mysql从另一个表更新

sql - SQL 中的多个分组依据

MySQL 使用 before 触发器更新同一个表

mysql - 在 where 子句中使用 select

MySQL自定义多表连接查询

php - 使用 PHP + MySQL 切换数据库有多快?

python - 使用 .groupby() 后重命名列的问题

python - Pandas :groupby 并创建一个新列,将聚合应用于两列