Присоединиться к одной строке с последней датой в Vertica - PullRequest
1 голос
/ 14 февраля 2020

Я хочу получить статус в таблице B, который был текущим на дату события в таблице A.

Table A
Person: Date:       Event
Bob     2020-01-05  Party

Table B
Person:  Date: Status
Bob      2020-01-08     Awake 
Bob      2020-01-03     Dinner
Bob      2020-01-01     Cycling

Таким образом, правильный результат будет

Bob     2020-01-05  Party Dinner

I попробовал это, но получил ошибку «Коррелированное выражение подзапроса без агрегатов и с ограничением не поддерживается».

SELECT 
    A.Person, 
    A.Date, 
    A.Event,
    (
        SELECT Status FROM B
        WHERE A.Person = B.Person AND B.Date <= A.Date
        ORDER BY B.Date desc
        LIMIT 1
    ) AS Status
FROM A

Может кто-нибудь сказать мне, что я должен сделать вместо этого? Я попробовал несколько других идей, но продолжаю сталкиваться с другими ошибками.

Ответы [ 2 ]

1 голос
/ 15 февраля 2020

Vertica имеет «Присоединение к серии событий»!

левое, правое или полное внешнее объединение двух таблиц с предикатом значения INTERPOLATE PREVIOUS, которое соединяет текущую строку с непосредственно предшествующей строкой другой таблицы в соответствии со столбцом соединения:

WITH 
a(person, dt,Event) AS (
SELECT 'Bob',DATE '2020-01-05','Party'
)
,
b(person,dt,status) AS (
          SELECT 'Bob', DATE '2020-01-08','Awake'
UNION ALL SELECT 'Bob', DATE '2020-01-03','Dinner'
UNION ALL SELECT 'Bob', DATE '2020-01-01','Cycling'
)
SELECT
  a.person
, a.dt
, a.event
, b.status
FROM a
LEFT OUTER JOIN b
 ON a.person = b.person
AND a.dt INTERPOLATE PREVIOUS VALUE b.dt
;
-- out  person |     dt     | event | status 
-- out --------+------------+-------+--------
-- out  Bob    | 2020-01-05 | Party | Dinner
1 голос
/ 14 февраля 2020

Если вы хотите получить результат только для одного человека, вы можете просто отсортировать и ограничить:

select
    a.person,
    a.date,
    a.event,
    b.status
from tablea a
inner join tableb b on b.person = a.person
where a.person = 'Bob'
order by b.date desc
limit 1

Если вы хотите обрабатывать более одного человека одновременно, можно использовать оконные функции. :

select *
from (
    select
        a.person,
        a.date,
        a.event,
        b.status,
        row_number() over(partition by a.person order by b.date desc) rn
    from tablea a
    inner join tableb b on b.person = a.person
) t
where rn = 1
...