mysql 通过第二个表中的特定值进行SELECT查询的通用SQL [已关闭]

k75qkfdt  于 12个月前  发布在  Mysql
关注(0)|答案(3)|浏览(115)

已关闭,此问题需要details or clarity。目前不接受答复。
**想改善这个问题吗?**通过editing this post添加详细信息并澄清问题。

5天前关闭。
Improve this question
我有两个表,它们表示一对多的关系
CREATE TABLE a( id int, a_text varchar(255) );
然后呢
CREATE TABLE b( a_id int, b_text varchar(255) );
其中列b_text包含枚举值。
表A:
| 身份证|a_text|
| - -----|- -----|
| 一个|'文本1'|
| 2| '文本2'|
表B:
| a_id| B_text|
| - -----|- -----|
| 一个|'状态1'|
| 一个|'状态2'|
| 2| '状态1'|
| 一个|'状态3'|
我想写一个SELECT查询,其中有几个b_text值作为参数,它返回表a中的所有行,这些行在连接后只包含给定的b_text值。例如,我想从表a中获取只有b_textstatus_1status_2的所有行。因此,id =1的行将被返回。
问题是:有没有一种方法可以编写一个通用的SQL查询,而不依赖于参数的数量?
我有一个解决方案,我只是用where语句为一个特定的值添加一个新的JOIN到B表中,但它不适合,因为没有办法动态添加一个新的join

eulz3vhy

eulz3vhy1#

您可以使用intersect:

Select * from a inner join b on a.id=b.a_id where status = 'status_1'
intersect 
Select * from a inner join b on a.id=b.a_id where status = 'status_2'

或者,您可以在以下情况下使用:

Select * from a where 
id in 
(select a_id from b where status='status_1')
and id in 
(select a_id from b where status='status_2')
klr1opcd

klr1opcd2#

编写查询的直接方法是:

select *
from a
where id in (select a_id from b where b_text = 'status_1')
  and id in (select a_id from b where b_text = 'status_2')
order by id;

这意味着对于每个状态,您必须添加一个带有AND的条件。
如果希望查询不随条件的数量而变化,则必须将所需的状态存储在单独的表中。例如,查询可能看起来像这样:

select *
from a
where not exists
(
  select null
  from desired
  where desired.b_text not in
  (
    select b.b_text
    from b 
    where b.a_id = a.id
  )
)
order by id;

或者,使用逗号分隔的列表代替单独的表(例如'status 1,status 2')沿着FIND_IN_SET

set @desired = 'status 1,status 2';

select *
from a
where id in
(
  select a_id
  from b
  where find_in_set (b_text, @desired)
  group by a_id
  having count(*) = (select char_length(@desired) - 
                            char_length(replace(@desired, ',', '')) + 1)
);

演示:https://dbfiddle.uk/0dC-PbEQ

mepcadol

mepcadol3#

在性能方面,我使用existslimit 1,因为我发现使用适当的索引,检查的行更少。

insert a values (1,'text 1'),(2,'text 2');
insert b values 
(1,'status 1'),
(1,'status 2'),
(2,'status 1'),
(1,'status 3');

select * 
from a
where exists (select 1 from b 
                where a.id=a_id and b_text='status 1'
                limit 1)
            and
        exists (select 1 from b 
                where a.id=a_id and b_text='status 2'
                limit 1)
;
-- without any index there are 12 rows examined:
Query_time: 0.001135  Lock_time: 0.000587 Rows_sent: 1  Rows_examined: 12 

-- here is the execution plan: 
+----+--------------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type        | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+--------------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | PRIMARY            | a     | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    2 |   100.00 | Using where |
|  3 | DEPENDENT SUBQUERY | b     | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    4 |    25.00 | Using where |
|  2 | DEPENDENT SUBQUERY | b     | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    4 |    25.00 | Using where |
+----+--------------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+

现在我们为a添加一个索引,为B添加另一个索引:

create index idx on a(id);
create index idx on b(a_id,b_text);

-- after indexing, rows examined are reduced to 5:
Query_time: 0.000934  Lock_time: 0.000596 Rows_sent: 1  Rows_examined: 5

-- here is the execution plan, which is much better as it uses index look-up as its access method and ref as the access type instead of a full table scan:
+----+--------------------+-------+------------+------+---------------+------+---------+-------------------+------+----------+-------------+
| id | select_type        | table | partitions | type | possible_keys | key  | key_len | ref               | rows | filtered | Extra       |
+----+--------------------+-------+------------+------+---------------+------+---------+-------------------+------+----------+-------------+
|  1 | PRIMARY            | a     | NULL       | ALL  | NULL          | NULL | NULL    | NULL              |    2 |   100.00 | Using where |
|  3 | DEPENDENT SUBQUERY | b     | NULL       | ref  | idx           | idx  | 263     | testdb.a.id,const |    1 |   100.00 | Using index |
|  2 | DEPENDENT SUBQUERY | b     | NULL       | ref  | idx           | idx  | 263     | testdb.a.id,const |    1 |   100.00 | Using index |
+----+--------------------+-------+------------+------+---------------+------+---------+-------------------+------+----------+-------------+

注意:limit 1子句实际上是多余的,因为EXISTS子查询隐式地覆盖了它。

相关问题