Язык Запро сов Beancount - SQL-подобные Финансовые Запросы
Beancount обладает мощным, SQL-подобным Языком Запросов (BQL), который позволяет вам нарезать, рассекать и анализировать ваши финансовые данные с высокой точностью. Хотите ли вы сгенерировать быстрый отчет, отладить запись или выполнить сложный анализ, освоение BQL является ключом к раскрытию всего потенциала вашей бухгалтерской книги в виде простого текста. Это руководство проведет вас через его структуру, функции и лучшие практики. 🔍
Структура и Выполнение Запросов
Ядром BQL является его знакомый, вдохновленный SQL синтаксис. Запросы выполняются с использованием инструмента командной строки bean-query, который обрабатывает ваш файл бухгалтерской книги и возвращает результаты непосредственно в ваш терминал.
Базовый Формат Запроса
Запрос BQL состоит из трех основных предложений: SELECT, FROM и WHERE.
SELECT <цель1>, <цель2>, ...
FROM <выражение-фильтра-записи>
WHERE <выражение-фильтра-проводки>;
SELECT: Указывает, какие столбцы данных вы хотите получить.FROM: Фильтрует целые транзакции до их обработки.WHERE: Фильтрует отдельные строки проводки после выбора транзакции.
Двухуровневая Система Фильтрации
Понимание разницы между предложениями FROM и WHERE имеет решающее значение для написания точн ых запросов. BQL использует двухуровневый процесс фильтрации.
-
Уровень Транзакции (
FROM) Это предложение действует на целые транзакции. Если транзакция соответствует условиюFROM, вся транзакция (включая все ее проводки) передается на следующий этап. Это основной способ фильтрации данных, поскольку он сохраняет целостность системы двойной записи. Например, фильтрацияFROM year = 2024выбирает все транзакции, которые произошли в 2024 году. -
Уровень Проводки (
WHERE) Это предложение фильтрует отдельные проводки внутри транзакций, выбранных предложениемFROM. Это полезно для представления и для фокусировки на конкретных частях транзакции. Однако имейте в виду, что фильтрация на этом уровне может "нарушить" целостность транзакции в выходных данных, поскольку вы можете увидеть только одну сторону записи. Например, вы можете выбрать все проводки в ваш счетExpenses:Groceries.
Модель Данных
Чтобы эффективно запрашивать ваши данные, вам нужно понимать, как Beancount их структурирует. Бухгалтерская книга - это список директив, но BQL в основном фокусируется на записях Transaction.
Структура Транзакции
Каждая Transaction является контейнером с атрибутами верхнего уровня и списком объектов Posting.
Transaction
├── date
├── flag
├── payee
├── narration
├── tags
├── links
└── Postings[]
├── account
├── units
├── cost
├── price
└── metadata
Доступные Типы Столбцов
Вы можете SELECT любой из атрибутов транзакции или ее проводок.
-
Атрибуты Транзакции Эти столбцы одинаковы для каждой проводки в рамках одной транзакции.
SELECT
date, -- Дата транзакции (datetime.date)
year, -- Год транзакции (int)
month, -- Месяц транзакции (int)
day, -- День транзакции (int)
flag, -- Флаг транзакции, например, "*" или "!" (str)
payee, -- Получатель (str)
narration, -- Описание или заметка (str)
tags, -- Набор тегов, например, #trip-2024 (set[str])
links -- Набор ссылок, например, ^expense-report (set[str]) -
Атрибуты Проводки Эти столбцы специфичны для каждой отдельной строки проводки.
SELECT
account, -- Название счета (str)
position, -- Полная сумма, включая единицы и стоимость (Position)
units, -- Количество и валюта проводки (Amount)
cost, -- Себестоимость проводки (Cost)
price, -- Цена, использованная в проводке (Amount)
weight, -- Позиция, преобразованная в ее себестоимость (Amount)
balance -- Текущий итог единиц на счете (Inventory)
Функции Запросов
BQL включает в себя набор функций для агрегации и преобразования данных, как и SQL.
Функции Агрегации
Функции агрегации суммируют данные по нескольким строкам. При использовании с GROUP BY они предоставляют сгруппированные сводки.
-- Подсчет количества проводок
SELECT COUNT(*)
-- Суммирование стоимости всех проводок (преобразованной в общую валюту)
SELECT SUM(position)
-- Найти дату первой и последней транзакции
SELECT FIRST(date), LAST(date)
-- Найти минимальное и максимальное значения позиции
SELECT MIN(position), MAX(position)
-- Сгруппировать по счету, чтобы получить сумму для каждого
SELECT account, SUM(position) GROUP BY account
Функции Позиции/Инвентаризации
Столбец position является составным объектом. Эти функции позволяют извлекать определенные части из него или вычислять его рыночную стоимость.
-- Извлечь только число и валюту из позиции
SELECT UNITS(position)
-- Показать общую стоимость позиции
SELECT COST(position)
-- Показать позицию, преобразованную в ее себестоимость (полезно для инвестиций)
SELECT WEIGHT(position)
-- Вычислить рыночную стоимость, используя последние данные о ценах
SELECT VALUE(position)
Вы можете комбинировать их для создания мощных отчетов. Например, чтобы увидеть общую стоимость и текущую рыночную стоимость вашего инвестиционного портфеля:
SELECT
account,
COST(SUM(position)) AS total_cost,
VALUE(SUM(position)) AS market_value
FROM
account ~ "Assets:Investments"
GROUP BY
account
Расширенные Функции
Помимо базовых операторов SELECT, BQL предлагает специализированные команды для создания общих финансовых отчетов.
Отчеты о Балансе
Оператор BALANCES генерирует баланс или отчет о прибылях и убытках за определенный период.
-- Сгенерировать простой баланс по состоянию на начало 2024 года
BALANCES FROM close ON 2024-01-01
WHERE account ~ "^Assets|^Liabilities"
-- Сгенерировать отчет о прибылях и убытках за 2024 финансовый год
BALANCES FROM
OPEN ON 2024-01-01
CLOSE ON 2024-12-31
WHERE account ~ "^Income|^Expenses"
Отчеты о Журнале
Оператор JOURNAL показывает подробную активность для одного или нескольких счетов, аналогично традиционному представлению бухгалтерской книги.
-- Показать всю активность на вашем расчетном счете по его первоначальной стоимости
JOURNAL "Assets:Checking" AT COST
-- Показать все транзакции 401k, отображая только единицы (акции)
JOURNAL "Assets:.*:401k" AT UNITS
Операции Печати
Оператор PRINT - это инструмент отладки, который выводит полные, соответствующие транзакции в их исходном формате файла Beancount.
-- Распечатать все транзакции, связанные с инвестициями, с 2024 года
PRINT FROM year = 2024
WHERE account ~ "Assets:Investments"
-- Найти транзакцию по ее уникальному идентификатору (сгенерированному некоторыми инструментами)
PRINT FROM id = "8e7c47250d040ae2b85de580dd4f5c2a"
Выражения Фильтрации
Вы можете создавать сложные фильтры, используя логические операторы (AND, OR), регулярные выражения (~) и сравнения.
-- Найти все расходы на поездки за вторую половину 2024 года
SELECT * FROM
year = 2024 AND month >= 6
WHERE account ~ "Expenses:Travel"
-- Найти все транзакции, связанные с отпуском или бизнесом
SELECT * FROM
"vacation-2024" IN tags OR
"business-trip" IN links
Соображения о Производительности ⚙️
bean-query разработан для эффективности, но понимание его операционного потока может помочь вам писать более быстрые запросы для больших бухгалтерских книг.
- Загрузка Данных: Beancount сначала анализирует весь ваш файл бухгалтерской книги и сортирует все транзакции в хронологическом порядке. Весь этот набор данных хранится в памяти.
- Оптимизация Запросов: Механизм запросов применяет фильтры в определенном порядке для максимальной эффективности:
FROM(транзакции) ->WHERE(проводки) -> Агрегации. Фильтрация на уровнеFROMявляется самой быстрой, потому что она уменьшает набор данных на ранней стадии. - Использование Памяти: Все операции происходят в памяти. Объекты
Positionи агрегацииInventoryоптимизированы, но очень большие наборы результатов могут потреблять значительный объем оперативной памяти. BQL не использует временное хранилище на диске.
Лучшие Практики
Следуйте этим советам, чтобы писать чистые, эффективные и удобные в обслуживании запросы.
-
Организация Запросов Форматируйте свои запросы для удобочитаемости, особенно сложные. Используйте разрывы строк и отступы для разделения предложений.
-- Чистый, удобочитаемый запрос для всех расходов за 2024 год
SELECT
date,
account,
position
FROM
year = 2024
WHERE
account ~ "Expenses"
ORDER BY
date DESC; -
Отладка Если запрос не работает должным образом, используйте
EXPLAIN, чтобы увидеть, как Beancount его анализирует. Чтобы протестировать фильтр, используйтеSELECT DISTINCT, чтобы увидеть, каким уникальным значениям он соответствует.-- Посмотреть план запроса
EXPLAIN SELECT date, account, position;
-- Проверить, какие счета соответствуют регулярному выражению
SELECT DISTINCT account
WHERE account ~ "^Assets:.*"; -
Утверждения Баланса Вы можете использовать BQL, чтобы перепроверить утверждения
balanceв вашей бухгалтерской книге. Этот запрос должен вернуть точную сумму, указанную в вашей последней проверке баланса для этого счета.-- Проверить оконча тельный баланс вашего расчетного счета
SELECT account, sum(position)
FROM close ON 2025-01-01 -- Используйте дату из вашей директивы balance
WHERE account = "Assets:Checking";