I need to get list of transactions
with list of logs
and tags
inside each transaction and the most important make search by field in logs
and tags
and unite it all.
Example below is search by field1
and tag1
. How to do that? Also important: I have 500m+ rows. If using WHERE id IN ..
will it be slow?
transactions
id int
hash var
id | hash
------------
1 | h1
2 | h2
3 | h3
logs
transaction_id int
field1 var
value var
transaction_id | field1 | value
-------------------------------
1 | f1 | v1
1 | f2 | v2
2 | f3 | v3
3 | f4 | v4
tags
transaction_id int
tag1 var
value var
transaction_id | tag1 | value
-------------------------------
1 | t1 | v1
2 | t2 | v2
2 | t3 | v3
I need result:
id | hash | logs_array | tags_array
------------------------------------------------------------------------------------------
1 | h1 | [{'field1': 'f1', 'value': 'v1'}, {'field1': 'f2', 'value': 'v2'}] | [{'tag1': 't1', 'value': 'v1'}]
2 | h2 | [{'field1': 'f3', 'value': 'v3'}] | [{'tag1': 't2', 'value': 'v2'}, {'tag1': 't3', 'value': 'v3'}]
3 | h3 | [{'field1': 'f4', 'value': 'v4'}] | []
Example template I can think of:
SELECT t.id, t.hash, array_agg(..) FROM transactions t WHERE id in
(
SELECT transaction_id FROM logs WHERE field1={any_string}
)
OR id in
(
SELECT transaction_id FROM tags WHERE tag1={any_string}
)
LEFT JOIN logs lo ON t.id = lo.transaction_id
LEFT JOIN tags ta ON t.id = ta.transaction_id
2
Answers
That could be accomplished with a query like this
Another version using conditions and stripping nulls
Fiddle to test
I think it’s preferable to do a pre-aggregation.
See example
Demo
Joins performance – there is no doubt about it. Surely there are suitable indexes.
The main cost of the operation will be in the search for WHERE field1={any string}, "full table scan" if no suitable indexes.