Beancount dispone di un potente linguaggio di interrogazione (BQL) simile a SQL che ti permette di sezionare, analizzare e interpretare con precisione i tuoi dati finanziari. Che tu voglia generare un rapido report, eseguire il debug di una registrazione o effettuare analisi complesse, padroneggiare BQL è fondamentale per sfruttare appieno il potenziale del tuo registro contabile in testo semplice. Questa guida ti illustrerà la sua struttura, le funzioni e le migliori pratiche. 🔍

Struttura ed Esecuzione delle Query
Il cuore di BQL è la sua sintassi familiare, ispirata a SQL. Le query vengono eseguite utilizzando lo strumento da riga di comando bea query, che elabora il tuo file di registro e restituisce i risultati direttamente nel terminale. Ogni query in questa guida è stata eseguita con Beancount 3.2.3 e beanquery 0.2.0.
Struttura Base di una Query
Una query BQL è composta da tre clausole principali: SELECT, FROM e WHERE.
SELECT <target1>, <target2>, ...
FROM <entry-filter-expression>
WHERE <posting-filter-expression>;SELECT: Specifica quali colonne di dati vuoi recuperare.FROM: Filtra intere transazioni prima che vengano elaborate.WHERE: Filtra le singole righe di registrazione dopo che la transazione è stata selezionata.
Sistema di Filtraggio su Due Livelli
Comprendere la differenza tra le clausole FROM e WHERE è fondamentale per scrivere interrogazioni accurate. BQL utilizza un processo di filtraggio su due livelli.
-
Livello Transazione (
FROM) Questa clausola agisce su intere transazioni. Se una transazione soddisfa la condizioneFROM, l'intera transazione (incluse tutte le sue registrazioni) viene passata alla fase successiva. Questo è il metodo principale per filtrare i dati, poiché preserva l'integrità del sistema di contabilità a partita doppia. Ad esempio, filtrareFROM year = 2024seleziona tutte le transazioni avvenute nel 2024. -
Livello di Registrazione (
WHERE) Questa clausola filtra le singole registrazioni all'interno delle transazioni selezionate dalla clausolaFROM. È utile per la presentazione e per concentrarsi su specifiche partite di una transazione. Tuttavia, tieni presente che il filtraggio a questo livello può "rompere" l'integrità di una transazione nell'output, poiché potresti vedere solo un lato di una registrazione. Ad esempio, potresti selezionare tutte le registrazioni sul tuo contoSpese:Alimentari.
Concretamente, PRINT FROM year = 2024 restituisce intere transazioni (entrambe le sezioni di ogni registrazione), mentre SELECT date, narration, account, position FROM year = 2024 WHERE account ~ "Assets:Broker" restituisce una riga per ogni registrazione corrispondente. Su un registro con due acquisti tramite broker, la prima restituisce le voci complete e la seconda esattamente le due righe del broker.
Modello dei Dati
Per interrogare i tuoi dati in modo efficace, devi capire come Beancount li struttura. Un registro è un elenco di direttive, ma BQL si concentra principalmente sulle voci Transaction.
Struttura della Transazione
Ogni Transaction è un contenitore con attributi di livello superiore e un elenco di oggetti Posting.
Transaction
├── date
├── flag
├── payee
├── narration
├── tags
├── links
└── Postings[]
├── account
├── units
├── cost
├── price
└── metadataTipi di Colonne Disponibili
Puoi SELECT qualsiasi attributo della transazione o delle sue registrazioni.
-
Attributi della Transazione Queste colonne sono le stesse per ogni registrazione all'interno di una singola transazione.
SELECT date, -- The date of the transaction (datetime.date) year, -- The year of the transaction (int) month, -- The month of the transaction (int) day, -- The day of the transaction (int) flag, -- The transaction flag, e.g., "*" or "!" (str) payee, -- The payee (str) narration, -- The description or memo (str) tags, -- A set of tags, e.g., #trip-2024 (set[str]) links -- A set of links, e.g., ^expense-report (set[str]) -
Attributi della Registrazione Queste colonne sono specifiche per ogni riga di registrazione individuale.
SELECT account, -- The account name (str) position, -- The full amount, including units and cost (Position) units(position), -- The number and currency of the posting (Amount) cost(position), -- The cost basis of the posting (Amount) price, -- The price used in the posting (Amount) weight, -- The position converted to its cost basis (Amount) balance -- The running total of units in the account (Inventory)unitsecostsono funzioni che prendonoposition.price,weightebalancesono colonne semplici.
Funzioni di Query
BQL include una suite di funzioni per l'aggregazione e la trasformazione dei dati, molto simile a SQL.
Funzioni di Aggregazione
Le funzioni di aggregazione riassumono i dati su più righe. Se usate con GROUP BY, forniscono riepiloghi raggruppati.
-- Count the number of postings
SELECT COUNT(*)
-- Sum all postings into one Inventory; currencies and lots are kept, not converted
SELECT SUM(position)
-- one row, e.g. (-2300.00 USD, 10 HOOL {150.00 USD, 2024-09-05}, 5 HOOL {160.00 USD, 2024-11-02})
-- Total one account in a single currency explicitly (positions without a price keep their currency)
SELECT SUM(CONVERT(position, 'USD')) WHERE account ~ "Assets:Checking"
-- one row, e.g. (2580.00 USD)
-- Find the date of the first and last transaction
SELECT FIRST(date), LAST(date)
-- Find the minimum and maximum position values
SELECT MIN(position), MAX(position)
-- Group by account to get a sum for each
SELECT account, SUM(position) GROUP BY accountFunzioni di Posizione/Inventario
La colonna position è un oggetto composito. Queste funzioni ti permettono di estrarne parti specifiche o di calcolarne il valore di mercato.
-- Extract just the number and currency from a position
SELECT UNITS(position)
-- Show the total cost of a position
SELECT COST(position)
-- Show each posting at its cost value (a column; there is no WEIGHT() function)
SELECT account, weight WHERE account ~ "Assets:Investments"
-- Calculate the market value using the latest price data
-- (needs a price directive for the holding; otherwise the position is returned unchanged)
SELECT VALUE(position)Puoi combinarle per ottenere report più complessi. Ad esempio, per vedere il costo totale e il valore di mercato attuale del tuo portafoglio di investimenti. Il valore di mercato richiede una direttiva price per ogni partecipazione, quindi ogni valuta viene riportata separatamente.
SELECT
account,
COST(SUM(position)) AS total_cost,
VALUE(SUM(position)) AS market_value
FROM
account ~ "Assets:Investments"
GROUP BY
account
-- one row per account, e.g. Assets:Broker:HOOL | (2300.00 USD) | (2625.00 USD)Funzionalità Avanzate
Oltre alle semplici istruzioni SELECT, BQL offre comandi specializzati per report finanziari comuni.
Report di Bilancio
L'istruzione BALANCES genera un prospetto patrimoniale o un conto economico per un periodo specifico.
-- Generate a simple balance sheet as of the start of 2024
BALANCES FROM close ON 2024-01-01
WHERE account ~ "^Assets|^Liabilities"
-- Generate an income statement for the 2024 fiscal year
BALANCES FROM
OPEN ON 2024-01-01
CLOSE ON 2024-12-31
WHERE account ~ "^Income|^Expenses"Report di Giornale
L'istruzione JOURNAL mostra l'attività dettagliata per uno o più conti, simile alla vista tradizionale di un libro mastro.
-- Show all activity in your checking account at its original cost
JOURNAL "Assets:Checking" AT COST
-- Show all 401k transactions, displaying only the units (shares)
JOURNAL "Assets:.*:401k" AT UNITSOperazioni di Stampa
L'istruzione PRINT è uno strumento di debug che restituisce le transazioni complete e corrispondenti nel loro formato originale di file Beancount. Accetta solo un filtro di registrazione. Una clausola WHERE qui è un errore di sintassi. Per restringere l'output a una sola partita di ogni registrazione, usa SELECT con un filtro sulle registrazioni. Restituisce una riga per ogni registrazione corrispondente.
-- Print all 2024 transactions in full (every posting of each matching entry)
PRINT FROM year = 2024
-- Show only the investment postings of 2024 transactions
SELECT date, narration, account, position
FROM year = 2024
WHERE account ~ "Assets:Investments"
-- Find a transaction by its unique ID (generated by some tools)
-- Returns the matching entry, or no rows when nothing carries that ID
PRINT FROM id = "8e7c47250d040ae2b85de580dd4f5c2a"Espressioni di Filtraggio
Puoi costruire filtri sofisticati utilizzando operatori logici (AND, OR), espressioni regolari (~) e confronti.
Le stringhe letterali sono racchiuse tra virgolette singole. Le virgolette doppie delimitano l'espressione regolare dopo ~.
-- Find all travel expenses from the second half of 2024
-- SELECT * returns date, flag, payee, narration and position per matching posting
SELECT * FROM
year = 2024 AND month >= 6
WHERE account ~ "Expenses:Travel"
-- Find all transactions related to a vacation or business
SELECT * FROM
'vacation-2024' IN tags OR
'business-trip' IN linksConsiderazioni sulle Prestazioni
bea query è progettato per l'efficienza, ma comprendere il suo flusso di lavoro può aiutarti a scrivere query più veloci su registri di grandi dimensioni.
- Caricamento dei Dati: Beancount prima analizza l'intero file di registro e ordina cronologicamente tutte le transazioni. L'intero set di dati viene mantenuto in memoria.
- Ottimizzazione della Query: Il motore applica i filtri in un ordine specifico per le prestazioni:
FROM(transazioni) →WHERE(registrazioni) → Aggregazioni. Il filtraggio a livelloFROMè il più rapido, poiché riduce il set di dati nelle fasi iniziali. - Utilizzo della Memoria: Tutte le operazioni avvengono in memoria. Le
Positione gli inventari sono ottimizzati, ma set di risultati molto grandi possono consumare molta memoria. Non viene utilizzato spazio su disco per l'archiviazione temporanea.
Migliori Pratiche
Per scrivere query pulite, efficaci e manutenibili, segui queste linee guida.
-
Formattazione Formatta le tue query per la leggibilità, separando le clausole su righe diverse.
-- A clean, readable query for all 2024 expenses SELECT date, account, position FROM year = 2024 WHERE account ~ "Expenses" ORDER BY date DESC; -
Debug Se una query non restituisce i risultati attesi, usa
LIMITper ridurre l'output eSELECT DISTINCTper vedere i valori univoci.-- Preview the first rows while iterating SELECT date, account, position LIMIT 5; -- Test which accounts match a regular expression SELECT DISTINCT account WHERE account ~ "^Assets:.*"; -
Verifica dei Saldi Puoi utilizzare BQL per verificare i saldi dei tuoi conti. Ad esempio, per controllare il saldo di un conto a una data specifica:
-- Verify the final balance of your checking account SELECT account, sum(position) FROM close ON 2025-01-01 -- Use the date from your balance directive WHERE account = "Assets:Checking";