SQL |如果存在另一个具有相等(b,c)的元组,则列出所有元组(a,b,c)

SQL |如果存在另一个具有相等(b,c)的元组,则列出所有元组(a,b,c),sql,postgresql,set,equality,Sql,Postgresql,Set,Equality,我有三个表,其中粗体属性是主键 餐厅(餐厅ID,名称,…) 标识符(餐厅ID,食品ID) 食品(食品ID,名称,…) 使用postgres,我想列出所有与至少一家其他餐厅共享同一套食物的餐厅(餐厅id和名称-每家餐厅1行) 比如说 ID为“1”的餐厅只有相关的食物ID为1和4,如标识符所示 ID为“3”的餐厅只有相关的食物ID为4和1,如标识符所示 ID为“7”的餐厅只有相关食物ID为6,如标识符所示 ID为“9”的餐厅只有相关食物ID为6,如标识符所示 然后输出 任何帮助都将不

我有三个表,其中粗体属性是主键

  • 餐厅(餐厅ID,名称,…)
  • 标识符(餐厅ID食品ID
  • 食品(食品ID,名称,…)
使用postgres,我想列出所有与至少一家其他餐厅共享同一套食物的餐厅(餐厅id和名称-每家餐厅1行)

比如说

  • ID为“1”的餐厅只有相关的食物ID为1和4,如
    标识符所示
  • ID为“3”的餐厅只有相关的食物ID为4和1,如
    标识符所示
  • ID为“7”的餐厅只有相关食物ID为6,如
    标识符所示
  • ID为“9”的餐厅只有相关食物ID为6,如
    标识符所示
  • 然后输出
任何帮助都将不胜感激


谢谢你

我理解你的问题,你希望所有餐厅的食物清单与餐厅1相同

如果是这样,那就是关系划分问题。下面是一种使用联接和聚合的方法:

select r.name
from identifier i1
inner join identifier i2 on i2.food_id = i1.food_id
inner join restaurant r on r.restaurant_id = i2.restaurant_id
where i1.restaurant_id = 1
group by r.restaurant_id
having count(*) = (select count(*) from identifier i3 where i3.restaurant_id = 1)

使用聚合函数
string\u agg()
获取每个餐厅的完整食物列表:

with cte as (
  select restaurant_ID,
         string_agg(food_ID::varchar(10),',' order by food_ID) foods
  from identifier
  group by restaurant_ID
)
select r.* 
from Restaurants r inner join cte c
on c.restaurant_ID = r.restaurant_ID
where exists (select 1 from cte where restaurant_ID <> c.restaurant_ID and foods = c.foods)

请参阅。

这里有一种方法可以获得一套独特的餐厅,它们拥有完全相同的食物。这使用了array_agg()和array_to_string()函数

 With cte as
(select T.restaurant_id, array_to_string(array_agg(food_id), ',') as food_list
from
(select *
  from Identifier t1
  order by restaurant_id, food_id) T
  group by T.restaurant_id)

select 
   concat(r1.name,',',r2.name) as resturant_names,
   t1.restaurant_id as restaurant_id1,
   r1.name as restaurant_1,
   t2.restaurant_id as restaurant_id2,
   r2.name as restaurant_2,
   t1.food_list as common_food_ids
from cte t1
join cte t2
on t1.restaurant_id < t2.restaurant_id
and t1.food_list = t2.food_list
left join Restaurants r1
on t1.restaurant_id = r1.restaurant_id
left join Restaurants r2
on t2.restaurant_id = r2.restaurant_id;

你的意思是你想在你的例子中列出id为1和3的两家餐馆,而不仅仅是3家。是吗?1.你的示例数据和解释不匹配?2.为什么只列出餐厅
3
而不列出
1
?您应该在问题中包含您试图解决此问题的代码。很抱歉,该示例中有错误。我现在已经修好了。如果有另外两家餐厅的食物收集完全相同,但与1号和3号餐厅的食物收集不同,该怎么办?在这种情况下,你的预期结果是什么?嘿,对不起,我意识到我写的那个问题非常糟糕。我想列出所有与至少一家其他餐厅共享同一套食物的餐厅。哇。。。非常感谢你抽出时间帮助一个陌生人。我以后一定会把我的问题弄清楚的!非常感谢您抽出时间回答!
Restaurant_id      name
1                  name1
3                  name3
7                  ...
9                  ...
select r.name
from identifier i1
inner join identifier i2 on i2.food_id = i1.food_id
inner join restaurant r on r.restaurant_id = i2.restaurant_id
where i1.restaurant_id = 1
group by r.restaurant_id
having count(*) = (select count(*) from identifier i3 where i3.restaurant_id = 1)
with cte as (
  select restaurant_ID,
         string_agg(food_ID::varchar(10),',' order by food_ID) foods
  from identifier
  group by restaurant_ID
)
select r.* 
from Restaurants r inner join cte c
on c.restaurant_ID = r.restaurant_ID
where exists (select 1 from cte where restaurant_ID <> c.restaurant_ID and foods = c.foods)
with cte as (
  select restaurant_ID,
         string_agg(food_ID::varchar(10),',' order by food_ID) foods
  from identifier
  group by restaurant_ID
)
select string_agg(r.name, ',') restaurants
from Restaurants r inner join cte c
on c.restaurant_ID = r.restaurant_ID
group by foods
having count(*) > 1
 With cte as
(select T.restaurant_id, array_to_string(array_agg(food_id), ',') as food_list
from
(select *
  from Identifier t1
  order by restaurant_id, food_id) T
  group by T.restaurant_id)

select 
   concat(r1.name,',',r2.name) as resturant_names,
   t1.restaurant_id as restaurant_id1,
   r1.name as restaurant_1,
   t2.restaurant_id as restaurant_id2,
   r2.name as restaurant_2,
   t1.food_list as common_food_ids
from cte t1
join cte t2
on t1.restaurant_id < t2.restaurant_id
and t1.food_list = t2.food_list
left join Restaurants r1
on t1.restaurant_id = r1.restaurant_id
left join Restaurants r2
on t2.restaurant_id = r2.restaurant_id;
With cte as
(select T.restaurant_id, array_to_string(array_agg(food_id), ',') as food_list
from
(select *
  from Identifier t1
  order by restaurant_id, food_id) T
  group by T.restaurant_id)

select 
   --concat(r1.name,',',r2.name) as resturant_names,
   t1.restaurant_id as restaurant_id,
   r1.name as restaurant--,
  --t2.restaurant_id as restaurant_id2,
  --r2.name as restaurant_2,
  --t1.food_list as common_food_ids
from cte t1
join cte t2
on t1.restaurant_id = t2.restaurant_id
and t1.food_list = t2.food_list
left join Restaurants r1
on t1.restaurant_id = r1.restaurant_id
left join Restaurants r2
on t2.restaurant_id = r2.restaurant_id;