Select from one table matching criteria in another?
Asked Answered
R

4

72

I'd really appreciate some help with an SQL query across tables. I realise this sort of thing is asked constantly, but I can't find a similar enough question to make sense of the answers.

I want to select rows from table_A that have a corresponding tag in table_B.
So, for example, " select rows from table_a which are tagged 'chair' " would return table_C.

Also, id is a unique in table_a, and not in table_b.

table_A:             table_B:                  table_C:

id    object         id    tag                 id    object
1     lamp           1     furniture           3     stool
2     table          2     furniture           4     bench
3     stool          3     furniture
4     bench          4     furniture
                     4     chair
                     3     chair

Alternatively, is there a better way to organise the data?

Rigobertorigor answered 27/3, 2011 at 2:15 Comment(0)
K
149

The simplest solution would be a correlated sub select:

select
    A.*
from
    table_A A
where
    A.id in (
        select B.id from table_B B where B.tag = 'chair'
)

Alternatively you could join the tables and filter the rows you want:

select
    A.*
from
    table_A A
inner join table_B B
    on A.id = B.id
where
    B.tag = 'chair'

You should profile both and see which is faster on your dataset.

Kettie answered 27/3, 2011 at 2:21 Comment(5)
@rjschnorenberg's suggestion is better if you have the luxury of changing the schema. In which case you would join the three tables Items<>Item_Tags<>Tags using two INNER JOIN clauses.Kettie
Great, that's very helpful. I wasn't aware you could filter columns from the joined table like that.Rigobertorigor
Actually you can also write the join line as "inner join table_B B on A.ID = B.ID AND B.tag = 'chair'" but I prefer to put filters under WHERE.Kettie
Which of these is "better" practice and performance wise? Or is it entirely preference?Gmt
That depends very much on the tables in question. In general, I use the first option if the select from B will produce a small number of records and the latter method if the number of B records is likely to be very high. However, they are similar enough that's it's not much effort to try both.Kettie
I
10

You should make tags their own table with a linking table.

items:
id    object
1     lamp  
2     table   
3     stool  
4     bench 

tags:
id     tag
1      furniture
2      chair

items_tags:
item_id tag_id
1       1
2       1
3       1
4       1
3       2
4       2
Intoxication answered 27/3, 2011 at 2:22 Comment(1)
This is the better answer assuming you have control over the schema. If you don't, consider creating a view which unions the two object tables so that you can then do what this answer suggests.Diamagnetism
S
3
select a.id, a.object
from table_A a
inner join table_B b on a.id=b.id
where b.tag = 'chair';
Starspangled answered 27/3, 2011 at 2:21 Comment(0)
N
2

I have a similar problem (at least I think it is similar). In one of the replies here the solution is as follows:

select
    A.*
from
    table_A A
inner join table_B B
    on A.id = B.id
where
    B.tag = 'chair'

That WHERE clause I would like to be:

WHERE B.tag = A.<col_name>

or, in my specific case:

WHERE B.val BETWEEN A.val1 AND A.val2

More detailed:

Table A carries status information of a fleet of equipment. Each status record carries with it a start and stop time of that status. Table B carries regularly recorded, timestamped data about the equipment, which I want to extract for the duration of the period indicated in table A.

Nonstop answered 25/5, 2018 at 6:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.