Ubu-Block stores all blockchain data in SQLite, making it easily queryable with standard SQL. This provides powerful analytics capabilities while maintaining blockchain integrity.
Get aggregated results for a specific constituency:
SELECT c.name as candidate, SUM(votes) as votes, ward_name as ward, constituency_name as constituency, county_name as county, parties.title as partyFROM results INNER JOIN stations ON stations.id = results.station_id INNER JOIN candidates c ON c.id = results.candidate_id INNER JOIN wards on stations.ward_code = wards.ward_code INNER JOIN parties ON parties.id = c.party_id INNER JOIN constituencies ON wards.constituency_code = constituencies.constituency_code INNER JOIN counties ON constituencies.county_code = counties.county_codeWHERE position_type = 'Mp' and constituency = 'Juja'GROUP BY candidate;
SELECT county_name as county, c.name as candidate, SUM(votes) as total_votesFROM results INNER JOIN stations ON stations.id = results.station_id INNER JOIN candidates c ON c.id = results.candidate_id INNER JOIN wards ON stations.ward_code = wards.ward_code INNER JOIN constituencies ON wards.constituency_code = constituencies.constituency_code INNER JOIN counties ON constituencies.county_code = counties.county_codeGROUP BY county_name, c.nameORDER BY county_name, total_votes DESC;
SELECT height, substr(hash, 1, 16) as hash, creator, timestamp, (SELECT COUNT(*) FROM results WHERE block_height = blocks.height) as result_countFROM blocksORDER BY height DESCLIMIT 10;
SELECT parties.title as party, COUNT(DISTINCT candidates.id) as candidate_count, SUM(votes) as total_votesFROM results INNER JOIN candidates ON results.candidate_id = candidates.id INNER JOIN parties ON candidates.party_id = parties.idGROUP BY parties.titleORDER BY total_votes DESC;
SELECT DATE(timestamp, 'unixepoch') as date, COUNT(*) as blocks_added, SUM((SELECT COUNT(*) FROM results WHERE block_height = blocks.height)) as total_resultsFROM blocksWHERE height > 0GROUP BY dateORDER BY date;
The database includes indexes on frequently queried columns. If you add custom tables, consider adding indexes:
CREATE INDEX idx_results_candidate ON results(candidate_id);CREATE INDEX idx_results_station ON results(station_id);
Filter early in queries
Apply WHERE clauses before JOINs when possible to reduce data processing:
-- Good: Filter firstSELECT * FROM results WHERE station_id = 123INNER JOIN stations ON ...-- Less efficient: Filter after joinSELECT * FROM resultsINNER JOIN stations ON ...WHERE station_id = 123
Use aggregations wisely
When aggregating large datasets, consider:
GROUP BY on indexed columns
LIMIT results for initial exploration
Using subqueries for complex aggregations
Quote SQL properly in shell
When using the CLI, quote your SQL to avoid shell interpretation:
# Goodubu-block query -q "SELECT * FROM results WHERE votes > 100"# May cause issuesubu-block query -q SELECT * FROM results WHERE votes > 100
Current version has a temporary limitation: query results must include columns candidate, votes, ward, constituency, county, and party. This will be removed in future versions.