select presto 上多列的不同连接

select distinct join on multiple column on presto

我有两张桌子。

因此表 1 看起来像:

+--------+-------------+--------
|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 .  |
| ...| ... |  ...      |  ...   |
+--------+-----------+----------

而表 2 是:

 +--------+------------+-------+-------
|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    |
| ...| ... |  ...      |   ... |...   |
+--------+-----------+-----------------

我想做什么来从表 2 中获取价格列并将其添加到基于三列 id1、id2 和日期的表 1 中。如果我像这样进行简单的连接

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 .  |
+--------+-----------+-------------------

使用群组

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

这涉及对您的数据的一些推测,但根据您的示例,如果您将排名列限制为值 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 及其派生词(包括按每一列分组,这本质上是 select 不同的),因为它给人一种非常随意的感觉——只需删除碰巧相同的任何记录。相反,我认为最好了解您的数据并知道为什么某些记录会被筛选掉。

例如,如果您确实想要选择具有最低 "rank" 值的记录,但并不总是保证值是 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 on,这是完全不同的,order by 使得保留哪条记录变得非常明确为什么。