选择其中的位置并具有相同的列

时间:2019-02-08 03:06:54

标签: sql postgresql

我有下表

amenity_venue (ids are uuids, made them ints for simplicty)
--------------------------
| amenity_id | venue_id  |
--------------------------
|     1      |     1     |
|     2      |     1     |
|     1      |     2     |
|     1      |     3     |

我正在尝试编写一个查询,该查询由amenity_id选择,但是只有venue_id兼有amenity_ids时才返回结果。

我知道这是坏的,但是类似:

select *
from amenity_venue where amenity_id in (1, 2)
having amenity_venue.venue_id = amenity_venue.venue_id

我的查询只能返回

--------------------------
| amenity_id | venue_id  |
--------------------------
|     1      |     1     |
|     2      |     1     |

因为地点1是同时拥有amenity_id 1和2的唯一地点。我如何编写这样的查询?

3 个答案:

答案 0 :(得分:1)

您可以使用聚合获取

select venue_id
from amenity_venue
where amenity_id in (1, 2) 
group by venue_id
having count(distinct amenity_id) = 2;  -- this is the number of values in the `in` list

如果表中没有重复项,则可以使用count(*)

如果您想要原始的行(而不仅仅是场地),那么我建议exists

select av.*
from amenity_venue av
where (av.amenity_id = 1 and
       exists (select 1 from amenity_venue av2 where av2.venue_id = av.venue_id and av2.amenity_id = 2)
      ) or
      (av.amenity_id = 2 and
       exists (select 1 from amenity_venue av2 where av2.venue_id = av.venue_id and av2.amenity_id = 1)
      );

答案 1 :(得分:0)

在添加新amenity_id的情况下,以下查询是可扩展的。

SELECT *
FROM amenity_venue
WHERE venue_id IN 
(
    --Get venue_id where all amenity_id exist
    SELECT venue_id 
    FROM amenity_venue
    GROUP BY venue_id
    HAVING count(*) = 
    (
        -- Get number of unique amenity_id
        SELECT count(DISTINCT amenity_id) FROM amenity_venue 
    )
)

答案 2 :(得分:0)

戈登答案的变体:

WITH cte AS
(
  select a.id as amenity_id, av.venue_id 
  from amenity a LEFT JOIN amenity_venue av ON a.id = av.amenity_id
  where a.id in (1,2)
)

SELECT av.*
FROM
  amenity_venue av
  INNER JOIN
  (
    SELECT venue_id
    FROM cte
    GROUP BY venue_id
    HAVING count(distinct amenity_id) =
    (select count(distinct amenity_id) from cte)
  ) x
  ON av.venue_id = x.venue_id

本质区别:

适用于您在此处列表中输入的任意数量的设施ID

以您要求的格式返回输出

工作方式:

您想知道列出所有设施的所有场地

我们将amenity_venue表减少为我们感兴趣的所有便利设施的列表(在您的情况下为1和2)。现在,我们想知道哪些场馆的设施各不相同

我们通过计算场所拥有的便利设施的数量并要求它等于列表中不同设施的数量来做到这一点。这是该组的目的(拥有/拥有)-它计算每个场所的不同设施,并将其与整个列表中不同的设施进行比较。

CTE包含一个LEFT JOIN,它会产生一个便利设施ID和具有该ID的场所的列表,但重要的是,如果没有场所拥有该设施,它还会产生一个与NULL配对的便利设施ID。因此,如果我们要求一个场所拥有设施1,2,3,那么这意味着CTE中设施的唯一列表为3,并且此查询:((select count(distinct amenity_id) from cte))的计数为3。但是,请记住,否场所具有设施3,因此最适合的场所(1)具有设施1和2,GROUP BY / HAVING将场所ID分组,并产生2种设施。因为3 <> 2,这意味着我们对“具有1,2,3便利设施的场所”的需求没有任何结果。如果我们没有剩下的这种联系,而仅仅依靠分配给场地的设施,那么要求1,2,3,将产生一个仅包含设施1和2的场地清单,这对将被单独计算设为2(应为3),查询将提供错误的结果

从该过程中获得场所ID列表后,场所ID将重新加入amenity_venue以检索请求的输出