MySQL strict select of rows involving many to many tables

我的梦境 提交于 2020-01-14 06:17:10

问题


I have three tables in the many-to-many format. I.e, table A, B, and AB set up as you'd expect.

Given some set of A ids, I need to select only the rows in AB that match all of the ids.

Something like the following won't work:

"SELECT * FROM AB WHERE A_id = 1 AND A_id = 2 AND A_id = 3 AND ... " As no single row will have more than one A_id

Using, an OR in the sql statment is no better as it yields results all results that have at least one of the A ids (whereas I only want those rows that have all of the ids).

Edit:

Sorry, I should explain. I don't know if the actual many-to-many relationship is relevant to the actual problem. The tables are outlined as follows:

Table People
int id
char name

Table Options
int id
char option

Table peoples_options
int id
int people_id
int option_id

And so I have a list of people, and a list of options, and a table of options and people.

So, given a list of option ids such as (1, 34, 44, ...), I need to select only those people that have all the options.


回答1:


A bit of a hacky solution is to use IN with a group by and having filter. Like so:

SELECT B_id FROM AB
WHERE A_id IN (1,2,3)
GROUP BY B_id
HAVING COUNT(DISTINCT A_id) = 3;

That way, you only get the B_id values that have exactly 3 A_id values, and they have to be from your list. I used DISTINCT in the COUNT just in case (A_id, B_id) isn't unique. If you need other columns, you could then join to this query as a sub-select in the FROM clause of another select statement.




回答2:


Your database doesn't appear to be normalized correctly. Your AB table should have a single A_id and a single B_id in each of its rows. If that were the case, your OR-version should work (although I would use IN myself).

Ignore the preceding paragraph. From your edit, you really wanted to know all the B's that have all of a subset of A's in the many-to-many table - see below for the query.

Please tell us the actual schema details, it's a little hard to figure out what you want without that.

I'd expect to see something like:

table a:
    a_id integer
    a_payload varchar(20)
table b:
    b_id integer
    b_payload varchar(20)
table ab:
    a_id integer
    b_id integer

Based on your description, the only thing I can think of is that you want a list of all the B's that have all of a set of A's in the AB table. In which case, you're looking at something like (to get the list of B's that have A's of 1, 3 and 4):

select distinct b_id from ab n1             
    where exists (select b_id from ab where a_id = 1 and b_id = n1.b_id)     
    and   exists (select b_id from ab where a_id = 3 and b_id = n1.b_id)     
    and   exists (select b_id from ab where a_id = 4 and b_id = n1.b_id);    

This works in DB2 but I'm not sure how much of SQL your chosen server implements.




回答3:


Try this....It brings all people that is associated with all options.

In other words the query bring all people that there it doesnt exists an option that were not associated to it.


select
    p.*
from
    people p
where
    not exists (
              select 
                      1 
              from 
                      options o
              where
                      not exists 
                      (
                          select 1
                          from   peoples_options po 
                          where  po.people_id     = p.people_id
                                 AND po.option_id = o.option_id
                      )
           )


来源:https://stackoverflow.com/questions/329822/mysql-strict-select-of-rows-involving-many-to-many-tables

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!