一尘不染

连接查询,只有在`in`子句中具有所有值的列

sql

我正在为我的网站创建一个简单的过滤系统。场地和便利设施之间存在许多关系。这是我的桌子。

注意:所有ID均为uuid。使它们简明扼要

场地:

| id    |      name      |
_________________________
| 'aaa' |  'first venue' |
| 'bbb' | 'second venue' |
| 'ccc' | 'third venue'  |

便利设施:

| id    |      name        |
___________________________
| 'aaa' |  'first amenity' |
| 'bbb' | 'second amenity' |
| 'ccc' | 'third amenity'  |

便利设施:

| amenity_id  |    venue_id  |
______________________________
| 'aaa'       |  'aaa'       |
| 'bbb'       | 'aaa'        |
| 'ccc'       | 'aaa'        |
| 'aaa'       | 'bbb'        |
| 'bbb'       | 'ccc'        |

我正在尝试编写查询以返回至少具有所有已通过amenity_ids传递的场所。例如,传入amenity_idsaaabbb

输出我正在寻找何时传入的设施ID是aaabbb

| id    |      name      |
_________________________
| 'aaa' |  'first venue' |

最初我尝试了这个查询

select * from venues 
INNER JOIN amenity_venue ON amenity_venue.venue_id = venues.id
where amenity_id in ('aaa', 'bbb');

这将返回所有具有amenity_idaaabbb

| id    |      name      |
_________________________
| 'aaa' |  'first venue' |
| 'bbb' | 'second venue' |
| 'ccc' | 'third venue'  |

所以我天真地尝试了

select * from venues 
INNER JOIN amenity_venue ON amenity_venue.venue_id = venues.id
where amenity_id = 'aaa'
  and amenity_id = 'bbb';

这什么也没返回。我正在尝试编写一个查询,其中返回amenity_idsaaabbb仅在场所传递的查询,aaa因为它是唯一与这两种便利设施都有关系的场所。而且,便利设施的数量在查询之间是动态的。


阅读 157

收藏
2021-03-17

共1个答案

一尘不染

您可以通过将ID汇总到一个数组中,然后将其与预期ID列表进行比较来做到这一点:

select v.*
from venues v
  join amenity_venue av ON av.venue_id = v.id
group by v.id
having array_agg(av.amenity_id) @> array['aaa', 'bbb'];

上面的示例假定已将venue.id其声明为主键(因为group by)。

如果您只想传递便利设施名称,则实际上并不需要对查询中的ID进行硬编码:

select v.*
from venues v
  join amenity_venue av ON av.venue_id = v.id
group by v.id
having array_agg(av.amenity_id) @> array(select id 
                                         from amenities 
                                         where name in ('first amenity', 'second amenity'));

在线示例:https//rextester.com/FNNVXO34389

2021-03-17