SQL: как построить запрос
От: sushko Россия  
Дата: 23.02.17 13:26
Оценка:
Есть две таблицы:

PAYMENTS
— date
— currency
— amount

RATES
— date
— currency
— rate

Как построить запрос, выводящий список сумм платежей в базовой валюте по курсу на дату платежа?

У меня получается так:
SELECT amount *     
    (
    SELECT rate FROM rates WHERE rates.currency=payments.currency AND rates.date=
        (
        SELECT MAX(date) FROM rates WHERE rates.currency=payments.currency AND rates.date<=payments.date
        )
    )
FROM payments


Получается два вложенных селекта, что (zope'ой чувствую) напряжет БД (как минимум FireBird) до изнеможения на большом наборе данных. Можно ли как-то решить этот вопрос проще?

При этом:
Бесплатный генератор отчетов для программ на C/C++
http://www.oxetta.com
Отредактировано 23.02.2017 13:39 sushko . Предыдущая версия . Еще …
Отредактировано 23.02.2017 13:38 sushko . Предыдущая версия .
Отредактировано 23.02.2017 13:29 sushko . Предыдущая версия .
Отредактировано 23.02.2017 13:27 sushko . Предыдущая версия .
Re: SQL: как построить запрос
От: _ABC_  
Дата: 23.02.17 14:19
Оценка: +2
Здравствуйте, sushko, Вы писали:

S>Как построить запрос, выводящий список сумм платежей в базовой валюте по курсу на дату платежа?

C SQLite ты ничего больше не придумаешь, ИМХО. Это сразу сужает способы решения задачи. Да и Firebird
не гигант в плане SQL...

Если только перестроишь таблицу rates так, чтобы у неё не было пропусков, тогда сможешь джойнить по дате платежа
без второго подзапроса.
Re[2]: SQL: как построить запрос
От: Mihas  
Дата: 23.02.17 14:42
Оценка:
Здравствуйте, _ABC_, Вы писали:

_AB>Если только перестроишь таблицу rates так, чтобы у неё не было пропусков, тогда сможешь джойнить по дате платежа

ИМХО, интересная идея. В году всего 365 дней — количество не гигантское. Можно построить индекс по дате и валюте, что еще ускорит выполнение.
Отредактировано 23.02.2017 14:43 Mihas . Предыдущая версия .
Re[3]: SQL: как построить запрос
От: sushko Россия  
Дата: 23.02.17 15:39
Оценка:
Здравствуйте, Mihas, Вы писали:

M>ИМХО, интересная идея. В году всего 365 дней — количество не гигантское. Можно построить индекс по дате и валюте, что еще ускорит выполнение.


Ничего не получится: в день может быть несколько изменений курса. В моем примере поле DATE правильнее было бы назвать DATE_AND_TIME
Бесплатный генератор отчетов для программ на C/C++
http://www.oxetta.com
Re[4]: SQL: как построить запрос
От: _ABC_  
Дата: 23.02.17 17:24
Оценка:
Здравствуйте, sushko, Вы писали:

S>Ничего не получится: в день может быть несколько изменений курса. В моем примере поле DATE правильнее было бы назвать DATE_AND_TIME

Тогда остается только твой вариант, т.к. SQLite с Firebird не скрестишь.
По отдельности вопрос решается, но несовместимыми средствами.
Re[4]: SQL: как построить запрос
От: Jester Канада  
Дата: 26.02.17 01:45
Оценка: 3 (1) +2
Здравствуйте, sushko, Вы писали:

S>Здравствуйте, Mihas, Вы писали:


M>>ИМХО, интересная идея. В году всего 365 дней — количество не гигантское. Можно построить индекс по дате и валюте, что еще ускорит выполнение.


S>Ничего не получится: в день может быть несколько изменений курса. В моем примере поле DATE правильнее было бы назвать DATE_AND_TIME


Я бы предложил добавить в таблицу Rates таймстемп закрытия курса и выставлять его по дате нового курса. Тогда можно будет просто использовать условие payments.date >= rates.dateopen and payments.date < rates.dateclose.
Re[5]: SQL: как построить запрос
От: _ABC_  
Дата: 26.02.17 05:41
Оценка:
Здравствуйте, Jester, Вы писали:

J>Я бы предложил добавить в таблицу Rates таймстемп закрытия курса и выставлять его по дате нового курса. Тогда можно будет просто использовать условие payments.date >= rates.dateopen and payments.date < rates.dateclose.

Rates.dateclose is null для действующего курса?
Если да, то для него платежи возвращаться не будут, нужно добавить проверку на этот факт тоже.

Но, вообще, решение вполне себе неплохое в условиях заданных ограничений.
Re[6]: SQL: как построить запрос
От: wildwind Россия  
Дата: 26.02.17 08:14
Оценка:
Здравствуйте, _ABC_, Вы писали:

_AB>Rates.dateclose is null для действующего курса?


Для действующего курса dateclose — константа из далекого будущего.

_AB>Но, вообще, решение вполне себе неплохое в условиях заданных ограничений.


В системах с большими объемами данных обычно используется этот подход. Серьезный минус — в необходимости поддерживать целостность на прикладном уровне, так как декларативно и триггерами это не опишешь (уж в Firebird точно). Но если производительность на первом месте, это оправдано.
Re[7]: SQL: как построить запрос
От: _ABC_  
Дата: 26.02.17 08:38
Оценка:
Здравствуйте, wildwind, Вы писали:

W>В системах с большими объемами данных обычно используется этот подход.

В системах с большими объемами данных используются обычно нормальные РСУБД, которые имеют
мощный синтаксис, а приложения заточены под конкретную РСУБД. Там способов решения проблем
несколько и оптимальный зависит от конкретных данных.
Re[6]: SQL: как построить запрос
От: Jester Канада  
Дата: 27.02.17 04:43
Оценка:
Здравствуйте, _ABC_, Вы писали:

_AB>Здравствуйте, Jester, Вы писали:


J>>Я бы предложил добавить в таблицу Rates таймстемп закрытия курса и выставлять его по дате нового курса. Тогда можно будет просто использовать условие payments.date >= rates.dateopen and payments.date < rates.dateclose.

_AB>Rates.dateclose is null для действующего курса?

Можно и по-другому: "условная бесконечность", например, 01.01.2500.
Re[7]: SQL: как построить запрос
От: _ABC_  
Дата: 27.02.17 05:05
Оценка:
Здравствуйте, Jester, Вы писали:

J>Можно и по-другому: "условная бесконечность", например, 01.01.2500.

Можно, конечно, вопросов нет.

Правда вон Сбербанк таким образом по нижней границе насчитал чего-то там с начала 20-го века.
В общем, нужно это искуственное ограничение учитывать в приложении.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.