Получение ближайшей даты к заданной дате в большом запросе без подзапросов

# #sql #google-bigquery #subquery

Вопрос:

Пытаюсь вернуться к курсу конвертации валюты на момент совершения покупки, чтобы расчет выручки был точным. BigQuery не поддерживает подзапросы, поэтому выполнение чего-то вроде этих 2 запросов не сработает (они работают с базой данных).:

Запрос 1

 SELECT
  b.id,
  j.id,
  j.currency,
  j.created,
  j.status,
  j.pricev,
  j.price,
  (
    select 
      erc.rfbcurr 
    from 
      test.exchangerates_exchangeratechange erc 
    join 
      test.exchangerates_exchangerate er on er.id = erc.exchangerateid
    where 
      erc.created < j.created and er.currencycode = j.currency 
    order by 
      erc.created desc
    limit 1
  ) as exchangerate
FROM 
  transferz-st.test.bs_b b
JOIN 
  transferz-st.test.bs_j j on j.bid = b.id;
 

Запрос 2

  SELECT
  b.id,
  j.id,
  j.currency,
  j.created,
  j.status,
  j.pricev,
  j.price,
  j.currency,
  erc.rfbcurr
FROM
  b
JOIN
  j on j.bid = b.id
JOIN
  exchangerate er on er.currencycode = j.currency
JOIN
  exchangeratechange erc on erc.exchangerateid = er.id
GROUP BY
  b.id,
  j.id,
  j.currency,
  j.created,
  j.status,
  j.pricevat,
  j.price,
  j.currency,
  erc.rfbcurr,
  erc.id
HAVING
    erc.id = (select erc2.id from exchangeratechange erc2 join exchangerate er2 on er2.id = rc2.id where erc2.created < j.created and er2.currencycode = j.currency order by erc2.created desc limit 1);
 

Кто-нибудь может предложить решение?

Комментарии:

1. Подзапросы поддержки больших запросов. можете ли вы указать, какую ошибку вы получаете.

2. Привет @Chandra. Спасибо за ваш ответ. Вот оно: Коррелированные подзапросы, ссылающиеся на другие таблицы, не поддерживаются, если они не могут быть декоррелированы, например, путем преобразования их в эффективное ОБЪЕДИНЕНИЕ.

Ответ №1:

Вы можете попробовать использовать a JOIN , чтобы ввести курсы валют. Используйте LEAD() для получения диапазона дат:

 WITH er AS (
      select erc.rfbcurr, er.currencycode, er.created, 
             lead(er.created) over (partition by er.currencycode order by er.created) as next_created
      from  test.exchangerates_exchangeratechange erc join 
            test.exchangerates_exchangerate er
            on er.id = erc.exchangerateid
     )
SELECT . . ., er.rfbcurr as exchange_rage
FROM transferz-st.test.bs_b b JOIN 
     transferz-st.test.bs_j j 
     ON j.bid = b.id JOIN
     er
     ON er.currencycode = j.currency AND
        j.created >= er.created AND
        (er.next_created IS NULL OR j.created < er.next_created);