【问题标题】:SQL query to find only those customer ids which have 2 source valuesSQL 查询仅查找具有 2 个源值的客户 ID
【发布时间】:2020-09-24 13:40:18
【问题描述】:

我有 2 个表,一个存储客户 ID,另一个存储客户 ID 以及有关使用该客户信息的不同来源的信息。例子: 表A

Customer Id
1
2
3
..

表 B

Customer Id Source
1            'AA'
2            'AA'
1            'AB'
2            'AB'
2            'AC'
3            'AA'
3            'AB'
3            'AE'
4            'AA'
4            'AB'

我想编写一个 SQL 查询,它返回只有 AA 和 AB 作为来源(没有其他来源)的记录

我已经编写了以下查询,但它不能正常工作:

select a.customer_id
  from A a, B b
 where a.customer_id = b.customer_id
   and b.source IN ('AA','AB')
 group by a.customer_id
having count(*) = 2;

【问题讨论】:

    标签: sql oracle join count


    【解决方案1】:

    一个相当有效的解决方案是几个exists 子查询:

    select a.*
    from a
    where
        exists(select 1 from b where b.customer_id = a.customer_id and b.source = 'AA')
        and exists(select 1 from b where b.customer_id = a.customer_id and b.source = 'AB')
        and not exists(select 1 from b where b.customer_id = a.customer_id and b.source not in ('AA', 'AB'))
    

    b(customer_id, source) 上有一个索引,这应该会运行得很快。

    另一种选择是聚合:

    select customer_id
    from b
    group by customer_id
    having
        max(case when source = 'AA' then 1 else 0 end) = 1
        and max(case when source = 'AB' then 1 else 0 end) = 1
        and max(case when source not in ('AA', 'AB') then 1 else 0 end) = 0
    

    【讨论】:

    • 谢谢,这应该可以工作,存在和不存在的组合。我会在这方面了解更多。
    【解决方案2】:

    这假设 customer_id/source 组合没有重复项

    select a.customer_id
      from A a join B b
        on a.customer_id = b.customer_id
     group by a.customer_id
    -- both 'AA' and 'AB', but no other
    having sum(case when b.source IN ('AA','AB') then 1 else -1 end) = 2
    

    在加入之前聚合可能更有效:

    select a.customer_id
    from A a join 
      ( select customer_id
        from B b
        group by customer_id
        -- both 'AA' and 'AB', but no other
        having sum(case when source IN ('AA','AB') then 1 else -1 end) = 2
      ) b
    on a.customer_id = b.customer_id
    

    【讨论】:

      【解决方案3】:

      你可以使用聚合:

      select b.customer_id
      from b
      where b.source in ('AA', 'AB')
      group by b.customer_id
      having count(distinct b.source) = 2;
      

      也就是说,您的版本应该可以工作。但是,您应该学会使用正确、明确、标准、可读的JOIN 语法。但是,在这种情况下不需要连接。

      如果你想要这两个来源,你需要调整逻辑:

      select b.customer_id
      from b
      group by b.customer_id
      having sum(case when b.source = 'AA' then 1 else 0 end) > 0 and  -- has AA
             sum(case when b.source = 'AB' then 1 else 0 end) > 0 and  -- has AB
             count(distinct b.source) = 2;
      

      【讨论】:

      • 此解决方案是否确保除了 'AA' 和 'AB' 之外不存在其他来源?
      • 第一个来源为 AA,第二个来源为 AC 且没有其他来源的记录也将被返回。
      • @AlokMathur 。 . .我错过了那部分要求,但更新了答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-07
      • 1970-01-01
      • 1970-01-01
      • 2013-10-11
      • 1970-01-01
      相关资源
      最近更新 更多