On 24/10/24 19:07, Daniel Schultz wrote:
Hello all,
I'm generating a campaign finance report, which means I need to load any
journal entries for accounts whose *total balance* exceeds $50.00
I figure this is not going to be possible via BQL directly but figured
it cannot hurt to ask.
The query I would love to use is something along the lines of:
```
SELECT
account,
date,
position,
getitem(open_meta(account), 'pac_name') AS pac_name,
getitem(open_meta(account), 'address') AS address,
getitem(open_meta(account), 'city') AS city,
getitem(open_meta(account), 'state') AS state,
getitem(open_meta(account), 'zip') AS zip,
getitem(open_meta(account), 'country') AS country,
getitem(open_meta(account), 'email') AS email,
getitem(open_meta(account), 'phone') AS phone
WHERE account ~ 'Income:Contributions'
AND getitem(open_meta(account), 'pac_name') != ''
AND account IN (
SELECT account
WHERE abs(sum(position)) > 50
)
ORDER BY date
```
This doesn't appear to work and I believe that is because subqueries are
not actually a thing in BQL. Are there any query tools that might help
be achieve this goal?
beanquery has some very limited support for subqueries. In particular,
it does not support subqueries that are not constants. However, it
didn't had support for subqueries on the right hand side of the IN
operator. Adding minimal support for it is relatively easy, so I did it,
see https://github.com/beancount/beanquery/pull/208. Expanding the
subquery support is in the works.
However, I guess that your attempt failed at an earlier stage of the
query interpretation: the subquery is invalid.
SELECT account WHERE abs(sum(position)) > 50
Because of the use of sum() this is aggregate query (the fact is
disguised by the use of the BQL auto-aggregate functionality) and it is
trying to filter the rows by the value of the aggregated column. This is
not a valid operation in SQL. The query would have to be rewritten in
this way:
SELECT account GROUP BY account HAVING abs(sum(position)) > 50
However, the condition for the HAVING clause is incorrect: sum(position)
returns an inventory, and the abs() of an inventory is still an
inventory, which cannot be compared with a number. You would need to
extract the amount of a single currency in the inventory, and get the
numerical part of the amount and discard the currency. I also thing the
use of abs() is not useful, as you are interested only in donors, thus
the inventory should always be positive. Therefore, the subquery becomes:
SELECT account
GROUP BY account
HAVING number(only('USD', sum(position))) > 50.0
However, this is computing a lot of inventories that are not really
useful for the outer query and making the set to be check by the IN
operator unnecessarily large. Adding a WHERE clause helps:
SELECT account
WHERE root(account, 2) = 'Income:Contributions'
GROUP BY account
HAVING number(only('USD', sum(position))) > 50.0
and you can drop the equivalent condition from the outer query.
Cheers,
Dan
--
You received this message because you are subscribed to the Google Groups
"Beancount" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/beancount/2417f1a7-0fc8-4ead-b015-39bf4b2292ff%40grinta.net.