【问题标题】:select unique matching rows in SQL based on two columns根据两列在 SQL 中选择唯一匹配的行
【发布时间】:2019-05-07 15:44:09
【问题描述】:

我有一个包含 314,044,452 行的表格,如下所示:

id1   id2   amount
---- ----   ------
a     A     2
a     A     1
a     A     3
b     B     1
b     B     5
c     A     6
c     A     6
d     F     2
d     F     3
d     F     4

我想返回一个表,其中仅返回基于 id2 的唯一匹配,即不返回带有 A 的行。加上金额是行的总和:

id1 id2 amount
--- --- ------
b   B    6
d   F    9

一个查询就可以做到吗?

【问题讨论】:

  • 你能详细说明unique matching based on id2是什么意思吗?你说A没有返回,但不清楚原因。
  • 当然,如果不同的 id1 与同一个 id2 匹配,那么这将不是唯一匹配。基本上,如果 id2 重复并且 id1 在重复中不同,则不应在结果中返回该行

标签: sql amazon-athena presto


【解决方案1】:

这是你要找的吗?

select id1, id2, sum(amount) amount
from <table>
where id2 <> 'A'
group by id1, id2;

【讨论】:

  • 谢谢。不,因为 id2 可以是任何东西,而不仅仅是 A。也许我应该更新这个例子。但例如,如果 F 与另一个 id1 重复,那么结果不应该出现在结果中
【解决方案2】:
SELECT MAX(id1), id2, SUM(amount) amount
FROM <table>
GROUP id2
HAVING COUNT(DISTINCT id1) = 1;

删除 A 因为有id1 = {a,c}

【讨论】:

  • 你试过了吗?
【解决方案3】:

如果我理解正确,您只想要不共享共同 id2 的唯一对,您会像这样得到它们:

select id1,id2,sum(amount) as amount
from 
<table> t 
join (
    select id2
    from <table>
    group by 1
    having count(distinct id1)=1
) unique_groups
on t.id2=unique_groups.id2
group by 1,2

考虑到行数,我实际上会先用unique pairs 创建一个临时表,然后将其加入源表。如果这不起作用或花费太长时间,您可以进一步分解它 - 首先实现不同的id1, id2,然后实现unique_groups,然后运行查询

【讨论】:

    【解决方案4】:

    尝试以下方法:

       SELECT DISTINCT id2, SUM(amount) from "tablename"
       group by id2
    

    如果我缺少您要查找的内容,请告诉我。

    【讨论】:

      【解决方案5】:

      此查询返回给定样本数据集的预期输出-

      WITH A (id1,id2,amount)
      AS
      (
          SELECT 'a','A',2
          UNION ALL
          SELECT 'a','A',1
          UNION ALL
          SELECT 'a','A',3
          UNION ALL
          SELECT 'b','B',1
          UNION ALL
          SELECT 'b','B',5
          UNION ALL
          SELECT 'c','A',6
          UNION ALL
          SELECT 'c','A',6
          UNION ALL
          SELECT 'd','F',2
          UNION ALL
          SELECT 'd','F',3
          UNION ALL
          SELECT 'd','F',4
      )
      SELECT id1,id2,SUM(amount)
      FROM A
      WHERE id2 <> 'A'
      GROUP BY id1,id2
      

      【讨论】:

        【解决方案6】:

        在分组和求和之前,您必须排除您不想参与的行,您可以使用NOT EXISTS

        select
           t.id1, 
           t.id2,
           sum(t.amount) amount
        from (
          select t.* from tablename t
          where not exists (
            select 1 from tablename
            where id1 <> t.id1 and id2 = t.id2
          )
        ) t
        group by t.id1, t.id2
        

        请参阅demo

        | id1 | id2 | amount |
        | --- | --- | ------ |
        | b   | B   | 6      |
        | d   | F   | 9      |
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-08-12
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多