【问题标题】:select distinct join on multiple column on presto在 presto 上的多个列上选择不同的连接
【发布时间】:2020-05-27 14:12:53
【问题描述】:

我有两张桌子。

所以 table1 看起来像:

+--------+-------------+--------
|id1 | id2 |  date     | degree |
+--------+-------------+--------
|  1 |  10 |  20200101 |   1    |
|  1 |  11 |  20200101 |   1    |
|  1 |  11 |  20200101 |   1    |
|  2 |  52 |  20200101 |   2 .  |
|  2 |  52 |  20200101 |   2 .  |
|  2 |  53 |  20200101 | . 2 .  |
|  3 |  21 |  20200101 |   2 .  |
| ...| ... |  ...      |  ...   |
+--------+-----------+----------

table2 是:

 +--------+------------+-------+-------
|id1 | id2 |  date     | price | rank |
+--------+-------------+-------+-------
|  1 |  10 |  20200101 |  1200 | 1    |
|  1 |  10 |  20200101 |  1200 | 2    |
|  1 |  10 |  20200101 |       |      |
|  1 |  10 |  20200101 |  1300 | 1    |
|  1 |  10 |  20200101 |  1300 | 2    |
| ...| ... |  ...      |   ... |...   |
+--------+-----------+-----------------

我想要从 table2 获取价格列并将其添加到基于三列 id1、id2 和日期的 table1。如果我像这样进行简单的加入

select tab1.id1, tab1.id2, tab1.date, tab2.price
from tab1
left join tab2
on tab1.id1 = tab2.id1
and tab1.id2 = tab2.id2
and tab1.date = tab2.date

这就是我们所拥有的:

 +--------+------------+----------------
|id1 | id2 |  date     | price | degree |
+--------+-------------+----------------
|  1 |  10 |  20200101 |  1200 |   1    |
|  1 |  10 |  20200101 |  1200 |   1    |
|  1 |  10 |  20200101 |       |   1    |
|  1 |  10 |  20200101 |  1300 |   1    |
|  1 |  10 |  20200101 |  1300 |   1    |
+--------+-----------+-------------------

但其实我想要的是这个:

 +--------+------------+----------------
|id1 | id2 |  date     | price | degree |
+--------+-------------+----------------
|  1 |  10 |  20200101 |  1200 | . 1 .  |
|  1 |  10 |  20200101 |  1300 |   1 .  |
+--------+-----------+-------------------

【问题讨论】:

  • 选择 Distinct 应该为您完成,以防您不想将它们组合在一起。

标签: sql postgresql presto


【解决方案1】:

使用组

select * from (
 select tab1.id1 as id1, tab1.id2 as id2, tab1.date as date, tab2.price as price
 from tab1
 left join tab2
 on tab1.id1 = tab2.id1
 and tab1.id2 = tab2.id2
 and tab1.date = tab2.date) as t group by t.id1,t.id2,t.date,t.price

【讨论】:

  • 感谢您的解决方案。我更新了问题并提出了后续问题:如果 table1 中有其他列想要包含在最终表中,例如示例中的 degree,我应该如何修改您的解决方案?
  • 首先在第二个 select 语句中选择它,然后用逗号将它添加到 group by 中,然后你就完成了。如果对您有帮助,请给出正确答案并投反对票
【解决方案2】:

这涉及对您的数据的一些推测,但根据您的示例,如果您将排名列限制为值 1,它将给出所需的结果。

select
  tab1.id1, tab1.id2, tab1.date, tab2.price
from
  tab1
  join tab2 on
    tab1.id1 = tab2.id1 and
    tab1.id2 = tab2.id2 and
    tab1.date = tab2.date and
    tab2.rank = 1 -- add this line

当然,如果整个数据集都不是这样,那么这将行不通。

在大多数情况下,我喜欢避免使用 select distinct 及其派生词(包括按每列分组,这本质上是一个选择不同的选项),因为它给人一种非常随意的感觉——只需删除任何碰巧的记录相同。相反,我认为最好了解您的数据并了解为什么某些记录会被筛选掉。

例如,如果您确实想选择具有最低“排名”值的记录,但并不总是保证其值为 1,则可以这样做:

select distinct on (tab1.id1, tab1.id2, tab1.date)
  tab1.id1, tab1.id2, tab1.date, tab2.price
from
  tab1
  join tab2 on
    tab1.id1 = tab2.id1 and
    tab1.id2 = tab2.id2 and
    tab1.date = tab2.date and
    tab2.rank = 1 -- add this line
order by
  tab1.id1, tab1.id2, tab1.date, tab2.rank

我知道我刚刚说过我避免使用select distinct,但这实际上是一个完全不同的select distinct onorder by 非常明确地说明了保留哪些记录以及保留的原因。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-19
    • 1970-01-01
    • 1970-01-01
    • 2021-06-05
    • 2019-11-18
    相关资源
    最近更新 更多