Reputation: 139
I have two tables, assets and asset_params.
assets
|asset_id| some_asset_data |
-----------------------------
| 1 | 'some data' |
| 2 | 'some other data'|
asset_params
|asset_param_id|asset_id|param_name|param_value|
------------------------------------------------
| 1 | 1 | 'Memory' | '4096' |
| 2 | 1 | 'OS' | 'Windows' |
| 3 | 2 | 'Memory' | '4096' |
| 4 | 2 | 'OS' | 'Linux' |
Now, how can i find assets which have parameters where they have a param called 'Memory' with value '4096' AND a param 'OS' with value 'Windows'.
Desired result is that i find one asset row, with id 1, in the example case.
I cant find a reasonable solution. Any help is appreciated.
Upvotes: 0
Views: 42
Reputation: 11
Something like this should work:
select * from assets where
assets_id in (select assets_id from asset_params
where name = "OS" and value = "Win")
and
assets_id in (select assets_id from asset_params
where name = "memory" and value = "4096")
If your tables are huge, this needs proper indexes. But you should always have good indexes anyway. ;)
Upvotes: 1
Reputation: 797
select * from assets a where
exists (select 1 from asset_params p
where name = "OS" and value = "Win" and a.asset_id=p.asset_id)
and exists (select 1 from asset_params p
where name = "memory" and value = "4096" and a.asset_id=p.asset_id)
Upvotes: 1
Reputation: 1269873
You can do this with aggregation and a having
clause:
select asset_id
from asset_params
where param_name = 'Memory' and param_value = '3096' or
param_name = 'OS' and param_value = 'Windows'
group by asset_id
having count(*) = 2;
Note: if you can have multiple parameters with the same name, you should use count(distinct param_name)
= 2.
This easily generalized. A more Postgres'ish way of writing it is:
select asset_id
from asset_params
where (param_name, param_value) in (('Memory', '3096'), ('OS', 'Windows'))
group by asset_id
having count(*) = 2;
Upvotes: 1