2016-11-25 3 views
0

Я хочу написать внешний запрос приложения SQL Server, подобный приведенному ниже, используя SQLAlchemy.OUTER APPLY в SQLAlchemy

Таблица FX может не иметь соответствующую строку в дате в таблице цен, поэтому мне нужно использовать OUTER APPLY, чтобы получить последнюю строку в таблице FX для каждой даты.

SELECT p.EffectiveDate, p.Close_ * FX.Rate as USD_PRICE 
FROM PRICE p 
OUTER APPLY (
    SELECT TOP 1 * 
    FROM FX 
    WHERE 
     FromCurrency = p.Currency 
     AND ToCurrency = 'USD' 
     AND ExRateDate <= p.EffectiveDate 
    ORDER BY ExRateDate DESC 
) fx 

Краткая предыстория на столах:

  • Таблица цен является таймсерией, который имеет EffectiveDate, валютный и Close_ Column. EffectiveDate является основным ключом.
  • Таблица FX имеет столбцы FromCurrCode, ToCurrCode, ExRateDate и Rate. Первичный ключ (FromCurrCode, ToCurrCode, ExRateDate)
  • Мой вариант использования - это присоединиться к таблицам PRICE и FX, чтобы получить цену в долларах США. Однако для данной таблицы EffectiveDate в таблице PRICE в этой таблице не может быть строка в таблице FX. Поэтому таблицы не могут быть объединены напрямую с FX.ExRateDate = PRICE.EffectiveDate. Чтобы решить эту проблему, нужно использовать OUTER APPLY, чтобы найти последнюю строку в таблице FX, что FX.ExRateDate является самым близким к PRICE.EffectiveDate

Кажется, что SQLAlchemy не поддерживает внешнее выражение применения , Я взглянул на Custom SQL Constructs and Compilation Extension. Но я не уверен, как создать пользовательские конструкции внешнего приложения. У вас есть пример?

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

Благодаря

ответ

0

Использование Correlated Subquery здесь решение с использованием OUTER JOIN:

sq = (
    session.query(FX.id.label("last_id")) 
    .filter(FX.FromCurrency == Price.Currency) 
    .filter(FX.ToCurrency == 'USD') 
    .filter(FX.ExRateDate <= Price.EffectiveDate) 
    .order_by(FX.ExRateDate.desc()) 
    .order_by(FX.id.desc()) # handle duplicates just in case 
    .limit(1) 
    .correlate(Price) 
    .as_scalar() 
) 

q = session.query(
    Price.EffectiveDate, 
    (Price.Close_ * FX.Rate).label("USD_PRICE"), 
).outerjoin(FX, FX.id == sq)