Querying Data in HeliosDB
Querying Data in HeliosDB
Last Updated: November 1, 2025 Version: v6.0 Phase 2 M1
Comprehensive guide to querying data in HeliosDB, from basic SELECT statements to advanced AI-powered queries.
Table of Contents
- Basic SELECT Queries
- Filtering with WHERE
- Joins
- Aggregations
- Window Functions
- Common Table Expressions (CTEs)
- JSON/JSONB Queries
- Array Queries
- Full-Text Search
- Vector Search
- Natural Language Queries (NL2SQL)
- Time-Series Queries
- Graph Queries
- Performance Optimization
Basic SELECT Queries
Select All Columns
-- Select everythingSELECT * FROM users;
-- Select specific columnsSELECT id, username, email FROM users;
-- Column aliasesSELECT id AS user_id, username AS name, email AS contact_emailFROM users;LIMIT and OFFSET (Pagination)
-- First 10 rowsSELECT * FROM users LIMIT 10;
-- Skip first 10, get next 10 (page 2)SELECT * FROM users LIMIT 10 OFFSET 10;
-- Better pagination (using keyset)SELECT * FROM usersWHERE id > 100ORDER BY idLIMIT 10;ORDER BY (Sorting)
-- Ascending order (default)SELECT * FROM users ORDER BY created_at ASC;
-- Descending orderSELECT * FROM users ORDER BY created_at DESC;
-- Multiple columnsSELECT * FROM usersORDER BY created_at DESC, username ASC;
-- NULL handlingSELECT * FROM usersORDER BY last_login NULLS LAST;DISTINCT (Remove Duplicates)
-- Unique usernamesSELECT DISTINCT username FROM users;
-- Distinct combinationsSELECT DISTINCT country, city FROM users;Filtering with WHERE
Comparison Operators
-- EqualitySELECT * FROM users WHERE id = 123;
-- InequalitySELECT * FROM users WHERE status != 'banned';
-- Greater than / Less thanSELECT * FROM products WHERE price > 100;SELECT * FROM products WHERE price <= 50;
-- BETWEEN (inclusive range)SELECT * FROM ordersWHERE order_date BETWEEN '2025-01-01' AND '2025-12-31';
-- IN (multiple values)SELECT * FROM usersWHERE status IN ('active', 'pending', 'verified');
-- NOT INSELECT * FROM usersWHERE status NOT IN ('banned', 'deleted');Pattern Matching
-- LIKE (case-sensitive)SELECT * FROM usersWHERE email LIKE '%@gmail.com';
-- ILIKE (case-insensitive)SELECT * FROM usersWHERE username ILIKE 'admin%';
-- Wildcards:-- % = any characters-- _ = single character
-- Examples:WHERE name LIKE 'A%' -- Starts with AWHERE name LIKE '%son' -- Ends with sonWHERE name LIKE '%admin%' -- Contains adminWHERE code LIKE 'US-__-2025' -- US-XX-2025NULL Handling
-- Check for NULLSELECT * FROM users WHERE last_login IS NULL;
-- Check for NOT NULLSELECT * FROM users WHERE last_login IS NOT NULL;
-- COALESCE (return first non-NULL)SELECT username, COALESCE(display_name, username) AS nameFROM users;
-- NULLIF (return NULL if equal)SELECT NULLIF(status, 'unknown') FROM users;Logical Operators
-- ANDSELECT * FROM usersWHERE status = 'active' AND created_at > '2025-01-01';
-- ORSELECT * FROM usersWHERE status = 'admin' OR status = 'moderator';
-- NOTSELECT * FROM usersWHERE NOT (status = 'banned' OR status = 'deleted');
-- Complex combinationsSELECT * FROM ordersWHERE (status = 'shipped' OR status = 'delivered') AND total_amount > 100 AND created_at > NOW() - INTERVAL '30 days';Joins
INNER JOIN
-- Only matching rows from both tablesSELECT u.username, p.title, p.created_atFROM users uINNER JOIN posts p ON u.id = p.user_id;LEFT JOIN (LEFT OUTER JOIN)
-- All rows from left table, matching from rightSELECT u.username, COUNT(p.id) AS post_countFROM users uLEFT JOIN posts p ON u.id = p.user_idGROUP BY u.id, u.username;RIGHT JOIN
-- All rows from right table, matching from leftSELECT u.username, p.titleFROM users uRIGHT JOIN posts p ON u.id = p.user_id;FULL OUTER JOIN
-- All rows from both tablesSELECT u.username, p.titleFROM users uFULL OUTER JOIN posts p ON u.id = p.user_id;CROSS JOIN (Cartesian Product)
-- Every combinationSELECT u.username, r.role_nameFROM users uCROSS JOIN roles r;Self Join
-- Join table to itself (e.g., employee-manager relationship)SELECT e.name AS employee, m.name AS managerFROM employees eLEFT JOIN employees m ON e.manager_id = m.id;Multiple Joins
SELECT u.username, p.title, c.content AS comment, c.created_at AS comment_dateFROM users uINNER JOIN posts p ON u.id = p.user_idINNER JOIN comments c ON p.id = c.post_idWHERE u.status = 'active'ORDER BY c.created_at DESC;Aggregations
Basic Aggregate Functions
-- COUNTSELECT COUNT(*) FROM users;SELECT COUNT(DISTINCT country) FROM users;
-- SUMSELECT SUM(amount) FROM orders;
-- AVGSELECT AVG(price) FROM products;
-- MIN / MAXSELECT MIN(created_at), MAX(created_at) FROM users;
-- Multiple aggregatesSELECT COUNT(*) AS total_orders, SUM(amount) AS total_revenue, AVG(amount) AS avg_order_value, MIN(amount) AS min_order, MAX(amount) AS max_orderFROM orders;GROUP BY
-- Group by single columnSELECT country, COUNT(*) AS user_countFROM usersGROUP BY countryORDER BY user_count DESC;
-- Group by multiple columnsSELECT country, city, COUNT(*) AS user_countFROM usersGROUP BY country, city;
-- With aggregatesSELECT user_id, COUNT(*) AS order_count, SUM(amount) AS total_spentFROM ordersGROUP BY user_idHAVING SUM(amount) > 1000ORDER BY total_spent DESC;HAVING (Filter After Grouping)
-- Find users with more than 10 postsSELECT user_id, COUNT(*) AS post_countFROM postsGROUP BY user_idHAVING COUNT(*) > 10;
-- Multiple conditionsSELECT category, AVG(price) AS avg_priceFROM productsGROUP BY categoryHAVING AVG(price) > 50 AND COUNT(*) > 10;Window Functions
ROW_NUMBER (Assign Row Numbers)
SELECT username, email, ROW_NUMBER() OVER (ORDER BY created_at) AS row_numFROM users;RANK and DENSE_RANK
-- RANK (gaps in ranking)SELECT username, score, RANK() OVER (ORDER BY score DESC) AS rankFROM leaderboard;
-- DENSE_RANK (no gaps)SELECT username, score, DENSE_RANK() OVER (ORDER BY score DESC) AS dense_rankFROM leaderboard;PARTITION BY (Group Window Functions)
-- Rank users within each countrySELECT username, country, score, RANK() OVER (PARTITION BY country ORDER BY score DESC) AS country_rankFROM users;LAG and LEAD (Access Previous/Next Rows)
-- Compare with previous rowSELECT order_date, amount, LAG(amount) OVER (ORDER BY order_date) AS prev_amount, amount - LAG(amount) OVER (ORDER BY order_date) AS changeFROM orders;
-- Look ahead to next rowSELECT order_date, amount, LEAD(amount) OVER (ORDER BY order_date) AS next_amountFROM orders;Running Totals
SELECT order_date, amount, SUM(amount) OVER (ORDER BY order_date) AS running_totalFROM orders;Moving Average
SELECT order_date, amount, AVG(amount) OVER ( ORDER BY order_date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW ) AS moving_avg_7_daysFROM orders;Common Table Expressions (CTEs)
Basic CTE
-- Define reusable queryWITH high_value_customers AS ( SELECT user_id, SUM(amount) AS total_spent FROM orders GROUP BY user_id HAVING SUM(amount) > 1000)SELECT u.username, u.email, hvc.total_spentFROM high_value_customers hvcJOIN users u ON hvc.user_id = u.idORDER BY hvc.total_spent DESC;Multiple CTEs
WITHactive_users AS ( SELECT id, username FROM users WHERE status = 'active'),recent_orders AS ( SELECT user_id, SUM(amount) AS total FROM orders WHERE created_at > NOW() - INTERVAL '30 days' GROUP BY user_id)SELECT au.username, COALESCE(ro.total, 0) AS revenue_30dFROM active_users auLEFT JOIN recent_orders ro ON au.id = ro.user_idORDER BY revenue_30d DESC;Recursive CTEs (Hierarchical Data)
-- Organizational hierarchyWITH RECURSIVE org_tree AS ( -- Base case: top-level managers SELECT id, name, manager_id, 0 AS level FROM employees WHERE manager_id IS NULL
UNION ALL
-- Recursive case: employees reporting to previous level SELECT e.id, e.name, e.manager_id, ot.level + 1 FROM employees e JOIN org_tree ot ON e.manager_id = ot.id)SELECT * FROM org_tree ORDER BY level, name;JSON/JSONB Queries
Extract JSON Fields
-- Extract as textSELECT profile->>'name' AS name FROM users;
-- Extract as JSONSELECT profile->'address' AS address FROM users;
-- Nested extractionSELECT profile->'address'->>'city' AS city FROM users;Filter on JSON Data
-- Exact matchSELECT * FROM usersWHERE profile->>'role' = 'admin';
-- JSON containsSELECT * FROM usersWHERE profile @> '{"verified": true}';
-- JSON existsSELECT * FROM usersWHERE profile ? 'premium_until';JSON Array Operations
-- Array lengthSELECT profile->'tags', jsonb_array_length(profile->'tags')FROM users;
-- Expand JSON array to rowsSELECT username, jsonb_array_elements_text(profile->'tags') AS tagFROM users;Modify JSON
-- Add/update fieldUPDATE usersSET profile = profile || '{"verified": true}'WHERE id = 123;
-- Remove fieldUPDATE usersSET profile = profile - 'temp_field'WHERE id = 123;Array Queries
Array Operations
-- Check if array contains valueSELECT * FROM postsWHERE 'rust' = ANY(tags);
-- All values matchSELECT * FROM postsWHERE 'published' = ALL(statuses);
-- Array overlapSELECT * FROM postsWHERE tags && ARRAY['rust', 'database'];
-- Array contains arraySELECT * FROM postsWHERE tags @> ARRAY['rust', 'tutorial'];Unnest Arrays
-- Expand array to rowsSELECT id, title, unnest(tags) AS tagFROM posts;Full-Text Search
Basic Text Search
-- Create indexCREATE INDEX idx_posts_content_fts ON posts USING GIN(to_tsvector('english', content));
-- SearchSELECT title, contentFROM postsWHERE to_tsvector('english', content) @@ to_tsquery('english', 'database & performance');Ranking Results
SELECT title, ts_rank(to_tsvector('english', content), query) AS rankFROM posts, to_tsquery('english', 'database & performance') queryWHERE to_tsvector('english', content) @@ queryORDER BY rank DESC;Vector Search
Dense Vector Search (HNSW)
-- Find similar productsSELECT name, embedding <=> query_embedding AS distanceFROM productsORDER BY distanceLIMIT 10;
-- Cosine similaritySELECT name, 1 - (embedding <=> query_embedding) AS similarityFROM productsORDER BY similarity DESCLIMIT 10;Hybrid Search (Dense + Sparse)
SELECT * FROM hybrid_search( table_name := 'products', query_text := 'wireless headphones', query_embedding := get_embedding('wireless headphones'), fusion_algorithm := 'rrf', k := 60, limit := 10);See Vector Search Guide for details.
Natural Language Queries (NL2SQL)
Basic NL2SQL
-- Ask in natural languageSELECT NL2SQL('Show me top 10 customers by revenue this month');
-- Automatically translates to:-- SELECT customer_id, SUM(amount) as revenue-- FROM orders-- WHERE order_date >= DATE_TRUNC('month', NOW())-- GROUP BY customer_id-- ORDER BY revenue DESC-- LIMIT 10With Context
-- Provide schema contextSELECT NL2SQL( 'Find users who haven''t logged in for 30 days', schema := 'public', tables := ARRAY['users', 'login_history']);See NL2SQL Guide for details.
Time-Series Queries
Time Bucketing
-- Group by 1-hour intervalsSELECT time_bucket('1 hour', created_at) AS hour, COUNT(*) AS events_countFROM eventsWHERE created_at > NOW() - INTERVAL '24 hours'GROUP BY hourORDER BY hour;Continuous Aggregates
-- Create materialized viewCREATE MATERIALIZED VIEW hourly_metricsWITH (timeseries_aggregate = true) ASSELECT time_bucket('1 hour', timestamp) AS hour, device_id, AVG(temperature) AS avg_temp, MAX(temperature) AS max_tempFROM sensor_dataGROUP BY hour, device_id;
-- Query aggregateSELECT * FROM hourly_metricsWHERE hour > NOW() - INTERVAL '7 days';See Time-Series Guide.
Graph Queries
Path Finding
-- Find friends of friendsSELECT nameFROM GRAPH_MATCH ( (a:users)-[:follows]->(b:users)-[:follows]->(c:users))WHERE a.id = 123 AND c.id != 123RETURN DISTINCT c.name;Shortest Path
SELECT shortest_path( start_node := 'user_123', end_node := 'user_456', max_depth := 6) FROM social_graph;See Graph Query Guide.
Performance Optimization
EXPLAIN ANALYZE
-- See query execution planEXPLAIN ANALYZESELECT * FROM users WHERE email = 'alice@example.com';Create Indexes
-- B-tree index (default)CREATE INDEX idx_users_email ON users(email);
-- Partial indexCREATE INDEX idx_active_users ON users(id) WHERE status = 'active';
-- Covering indexCREATE INDEX idx_users_email_username ON users(email, username);
-- Expression indexCREATE INDEX idx_users_lower_email ON users(LOWER(email));Query Hints
-- Force index usageSELECT /*+ INDEX(users idx_users_email) */ * FROM users WHERE email = 'alice@example.com';
-- Disable sequential scanSET enable_seqscan = OFF;SELECT * FROM users WHERE email = 'alice@example.com';SET enable_seqscan = ON;Last Updated: November 1, 2025 Version: v6.0 Phase 2 M1 Maintained by: HeliosDB Documentation Team
Next: Data Types Reference →