Beancount 查询语言 - 类 SQL 财务查询
Beancount 具有强大的类 SQL 查询语言 (BQL),可让您精确地切片、切块和分析您的财务数据。 无论您是想生成快速报告、调试条目还是执行复杂分析,掌握 BQL 都是释放您的纯文本会计账本的全部潜力的关键。 本指南将引导您了解其结构、功能和最佳实践。 🔍
查询结构和执行
BQL 的核心是其熟悉的、受 SQL 启发的语法。 查询使用 bean-query 命令行工具执行,该工具处理您的账本文件并将结果直接返回到您的终端。
基本查询格式
BQL 查询由三个主要子句组成:SELECT、FROM 和 WHERE。
SELECT <target1>, <target2>, ...
FROM <entry-filter-expression>
WHERE <posting-filter-expression>;
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"
-- 通过其唯一 ID 查找交易(由某些工具生成)
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