СЛЕДУЕТ ПРИСОЕДИНИТЬСЯ К самой последней дате в Google BigQuery - PullRequest
0 голосов
/ 11 декабря 2018

У меня есть две таблицы, обе с метками времени и некоторыми другими данными:

Таблица A

| name | timestamp           | a_data |
| ---- | ------------------- | ------ |
| 1    | 2018-01-01 11:10:00 | a      |
| 2    | 2018-01-01 12:20:00 | b      |
| 3    | 2018-01-01 13:30:00 | c      |

Таблица B

| name | timestamp           | b_data |
| ---- | ------------------- | ------ |
| 1    | 2018-01-01 11:00:00 | w      |
| 2    | 2018-01-01 12:00:00 | x      |
| 3    | 2018-01-01 13:00:00 | y      |
| 3    | 2018-01-01 13:10:00 | y      |
| 3    | 2018-01-01 13:10:00 | z      |

Что я хочуdo is

  1. Для каждой строки в Таблица A LEFT JOIN самая последняя запись в Таблица B , которая предшествует ей.
  2. Когда есть более одной возможности, возьмите последнюю

Целевой результат

| name | timestamp           | a_data | b_data |
| ---- | ------------------- | ------ | ------ |
| 1    | 2018-01-01 11:10:00 | a      | w      |
| 2    | 2018-01-01 12:20:00 | b      | x      |
| 3    | 2018-01-01 13:30:00 | c      | z      | <-- note z, not y

Я думаю, что это включает подзапрос, но я не могу получить этоработать в Big Query.Что у меня есть:

SELECT a.a_data, b.b_data
FROM `table_a` AS  a  

LEFT JOIN `table_b` AS b 
ON a.name = b.name

WHERE a.timestamp = (
  SELECT max(timestamp) from `table_b` as sub
  WHERE sub.name = b.name
  AND sub.timestamp < a.timestamp
)

На моем фактическом наборе данных, который является очень маленьким набором тестов (менее 2 МБ), запрос выполняется, но никогда не завершается.Любые указатели очень ценятся 10

Ответы [ 4 ]

0 голосов
/ 12 декабря 2018

это распространенный случай, когда вы не можете просто Group by и получить минимум.Я предлагаю следующее:

SELECT *
FROM table_a as a inner join (SELECT name, min(timestamp) as timestamp
                              FROM table_b group by 1) as b 
on (a.timestamp = b.timestamp and a.name = b.name)

Таким образом, вы ограничиваете его только минимумом, указанным в таблице b, как вы указали.

Вы также можете добиться этого более читабельным способом, используя оператор WITH:

WITH min_b as (
SELECT name, 
min(timestamp) as timestamp
FROM table_b group by 1
)
SELECT *
FROM table_a as a inner join min_b 
on (a.timestamp = min_b.timestamp and a.name = min_b.name) 

Дайте мне знать, если это сработало!

0 голосов
/ 11 декабря 2018

В BigQuery массивы часто являются эффективным способом решения таких проблем:

SELECT a.a_data, b.b_data
FROM `table_a` a LEFT JOIN
     (SELECT b.name,
             ARRAY_AGG(b.b_data ORDER BY b.timestamp DESC LIMIT 1)[OFFSET(1)] as b_data
      FROM `table_b` b 
      GROUP BY b.name
     ) b
     ON a.name = b.name;
0 голосов
/ 12 декабря 2018

Ниже для стандартного SQL BigQuery и не требует указания всех столбцов с обеих сторон - только name и timestamp.Таким образом, он будет работать для любого числа столбцов в обеих таблицах (при условии отсутствия двусмысленности в названии, а не для вышеупомянутых двух столбцов)

#standardSQL
SELECT a.*, b.* EXCEPT (name, timestamp)
FROM (
  SELECT 
    ANY_VALUE(a) a, 
    ARRAY_AGG(b ORDER BY b.timestamp DESC LIMIT 1)[SAFE_OFFSET(0)] b
  FROM `project.dataset.table_a` a
  LEFT JOIN `project.dataset.table_b` b
  USING (name)
  WHERE a.timestamp > b.timestamp
  GROUP BY TO_JSON_STRING(a)
)
0 голосов
/ 11 декабря 2018

Вы можете попытаться использовать подзапрос выбора.

SELECT a.*,(
    SELECT MAX(b.b_data) 
    FROM `table_b` AS b 
    WHERE 
        a.name = b.name 
    and  
        b.timestamp < a.timestamp
) b_data 
FROM `table_a` AS  a

РЕДАКТИРОВАТЬ

Или вы можете попробовать использовать оконную функцию ROW_NUMBER в подзапросе.

SELECT name,timestamp,a_data , b_data
FROM (
    SELECT a.*,b.b_data,ROW_NUMBER() OVER(PARTITION BY a.name ORDER BY b.timestamp desc,b.name desc) rn 
    FROM `table_a` AS  a  
    LEFT JOIN `table_b` AS b ON a.name = b.name AND b.timestamp < a.timestamp
) t1
WHERE rn = 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...