【问题标题】:How to extract only rows that contain fields in a given list?如何仅提取包含给定列表中字段的行?
【发布时间】:2021-11-23 10:54:07
【问题描述】:

假设我有 2 张桌子一张 User

userId userName
123 user1
124 user2

和另一个Items

userId itemName
123 "item1"
123 "item2"
124 "item1"

有没有办法获取在给定列表(say ["item1","item2"]) 中拥有所有项目的所有用户的列表,即在这种情况下,只有用户 - 123 是有效响应。在这种情况下,以下将是预期的响应

userId userName
123 user1

现在我正在考虑使用in ("item1","item2") 提取数据,然后在内存中处理它。 我正在寻找一种使用查询来完成此任务的方法。

【问题讨论】:

  • 样本数据很好,但您还需要使用相同的格式指定预期结果。
  • 您想要那些完全拥有这两项的用户吗?或者至少这两项?

标签: sql postgresql


【解决方案1】:

试试:

select u.userId,u.userName
from Users u 
inner join ( select userId
             from Items
             where itemName in ('item1','item2')
             group by userId
             having count(itemName)=2
            ) as i  on u.userId=i.userId;

演示:https://www.db-fiddle.com/f/7yUJcuMJPncBBnrExKbzYz/168

子查询仅返回 Items 表中的 userId 并同时具有 itemName。

【讨论】:

  • 请注意,可怕的反引号在 Postgres 和标准 SQL 中是无效的。
【解决方案2】:
select u.* from User u
  join (select userId from Items where itemName='item1' 
  intersect
  select userId from Items where itemName='item2') sub 
on u.userId=sub.userId;

【讨论】:

  • 虽然此代码 sn-p 可能会解决问题,但including an explanation 将帮助人们了解您的代码建议的原因。
【解决方案3】:

EXISTSHAVING 一起使用可以做到这一点。

SELECT *
FROM Users AS usr
WHERE EXISTS (
  SELECT 1
  FROM Items AS itm
  WHERE itm.userId = usr.userId
    AND itm.itemName IN ('item1', 'item2')
  HAVING COUNT(DISTINCT itm.itemName) = 2
);
userid username
123 user1

db小提琴here

【讨论】:

    【解决方案4】:
    select *.u from
    user u 
    inner join (select * from item where item ='item1') a on a.id=u.id --they have item1
    inner join (select * from item where item ='item2') b on b.id=a.id --they have item2
    ;
    

    只需要同时拥有两者的用户,sql fiddle

    经过你的解释

    select count(*), u.id from
    user u 
    inner join (select * from item where item in ('item1','item2')) a on  a.id=u.id
    having count(*)>1
    

    【讨论】:

    • 这适用于 2 个项目,但如果我有一个项目列表怎么办。我将编辑问题。
    • 啊,我明白了,我还以为是这种特殊情况。我们也可以在 Items 中说您永远不会有重复项吗?
    • 否,如示例中的用户表中的每一行在项目表中可以有多个映射行,这些对于给定用户将是不同的,但在多个用户之间,项目可能会重复,例如“item1”这里重复。
    【解决方案5】:

    with 子句和数组比较:(postgres)

    with base_data as (
    select 
    userId,
    array_agg(itemName) over (partition by userId) as liste
    from Items
    )
    select 
    * from base_data
    where liste @> array['item1','item2']::varchar[]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-02
      • 1970-01-01
      • 2017-12-30
      • 2016-09-28
      • 2013-05-19
      • 1970-01-01
      相关资源
      最近更新 更多