Home > other >  How to select multiple records from a table with one field?
How to select multiple records from a table with one field?

Time:06-24

Hi guys I've got a situation like this:

There is a table WH_AT:

ID Warehouse_ID Attribute_ID
1 W01 101
2 W01 201
3 W02 106
4 W02 209
5 W03 156
6 W03 201

And what I want to search, is all warehouses (warehouse_ID) that has BOTH Attribute_ID 101 and 201 for example. Now I know that select * from WH_AT where Attribute_Id = 101 and Attribute = 201 won't work, but I tried self-joins and failed miserably (i tried:

select * 
from WH_AT w1 
join WH_AT w2 on w1.ID = w2.ID
where w1.Attribute_ID = 101 and w2.Attribute_ID = 201

unfortunately got some errors, and while specyfying w1.ID != w2.ID it returned basicaly the whole table.

How do i get Warehouse_IDs that has both Attributes: 101 and 201? And how to write a query as simple as possible, to be possibly most effective?

CodePudding user response:

Query: (no self-join needed regardless of how many attributes are required; what is required is writing them in the where clause, and counting them for the having clause)

select warehouse_id
from   wh_at
where  attribute_id in (101, 201)
group  by warehouse_id
having count(distinct attribute_id) = 2
;

With the sample data documented at the end, this produces the following output:

WAREHOUSE_ID
------------
W01
W04

The test data is shown below. I added a few more examples, to make sure the query works correctly for those cases. Especially the last example, where the same attribute is shown for the same warehouse more than once. (Perhaps this is not possible in your data due to a unique constraint, but if that is so, then you should mention it in your question.)

create table wh_at (id, warehouse_id, attribute_id) as
  select  1, 'W01', 101 from dual union all
  select  2, 'W01', 201 from dual union all
  select  3, 'W02', 106 from dual union all
  select  4, 'W02', 209 from dual union all
  select  5, 'W03', 156 from dual union all
  select  6, 'W03', 201 from dual union all
  select  7, 'W04', 101 from dual union all
  select  8, 'W04', 201 from dual union all
  select  9, 'W04', 303 from dual union all
  select 10, 'W05', 101 from dual union all
  select 11, 'W05', 101 from dual
;

CodePudding user response:

You are very close. Your query is almost correct.

You can join the table with itself. The first one to search for 101, the second one to search for 102. Then, a join can find the matching warehouses. For example:

select distinct a.warehouse_id
from wh_at a
join wh_at b on b.warehouse_id = a.warehouse_id
where a.attribute_id = 101 and b.attribute = 102
  • Related