Query of Queries
Execute SQL queries against in-memory query result sets for powerful data manipulation
Query of Queries (QoQ) allows you to execute SQL queries against in-memory query result sets, eliminating the need for additional database round trips. BoxLang's QoQ implementation is built from scratch using a high-performance ANTLR grammar based on SQLite, delivering exceptional speed and a comprehensive feature set that surpasses traditional CFML implementations.
📋 Overview
BoxLang's Query of Queries provides:
Fast Performance, optimized for large datasets
ANSI JOIN syntax - INNER, LEFT, RIGHT, FULL, and CROSS joins
Unlimited table joins - No restrictions on number of tables
Subqueries - Nested SELECT statements in FROM, JOIN, and IN clauses
CASE statements - Standard and input-based CASE expressions
Custom functions - Register your own scalar and aggregate functions
Complete SQL syntax - TOP/LIMIT, UNION, DISTINCT, GROUP BY, ORDER BY
Bitwise operators - XOR, AND, OR, NOT operations
Type safety - Preserves column types and NULL handling
🚀 Basic Usage
To execute a query of queries, set the dbtype option to "query":
// Create source data
employees = queryNew(
"name,department,salary,hireDate",
"varchar,varchar,integer,date",
[
[ "John Doe", "Engineering", 75000, createDate( 2020, 1, 15 ) ],
[ "Jane Smith", "Marketing", 68000, createDate( 2019, 3, 22 ) ],
[ "Bob Johnson", "Engineering", 82000, createDate( 2018, 7, 10 ) ],
[ "Alice Williams", "Sales", 71000, createDate( 2021, 5, 5 ) ]
]
);
// Query the query
result = queryExecute(
"SELECT name, salary FROM employees WHERE department = ?",
[ "Engineering" ],
{ dbtype: "query" }
);
// Result contains 2 rows: John Doe and Bob Johnson
writeOutput( "Found #result.recordCount# engineers" );🔗 ANSI JOIN Syntax
BoxLang supports modern ANSI JOIN syntax with unlimited table joins and full alias support.
INNER JOIN
Returns only matching rows from both tables:
LEFT (OUTER) JOIN
Returns all rows from the left table, with NULLs for non-matching right table rows:
RIGHT (OUTER) JOIN
Returns all rows from the right table, with NULLs for non-matching left table rows:
FULL (OUTER) JOIN
Returns all rows from both tables, with NULLs where matches don't exist:
CROSS JOIN
Returns the Cartesian product of both tables (every combination):
Multiple Table Joins
Join as many tables as needed:
🧩 Subqueries
BoxLang supports non-correlated subqueries in multiple contexts.
FROM/JOIN Subqueries
Use a subquery as a table source:
IN/NOT IN Subqueries
Filter using a subquery result set:
🎯 CASE Statements
CASE expressions provide conditional logic within SQL queries.
Standard CASE
Each WHEN contains a boolean expression:
Input CASE
Compare against a single input expression:
CASE in ORDER BY
📊 Aggregate Functions
BoxLang supports all standard aggregate functions plus powerful additions.
Standard Aggregates
String Aggregation
Concatenate values with delimiters:
🔧 Built-In Functions
BoxLang provides a comprehensive set of SQL functions.
Math Functions
Available: abs(), acos(), asin(), atan(), cos(), sin(), tan(), exp(), sqrt(), ceiling(), floor()
String Functions
Available: upper(), lower(), ucase(), lcase(), concat(), left(), right(), length(), ltrim(), rtrim()
NULL Handling
Available: coalesce(), isNull()
Type Conversion
Available: cast(), convert()
🛠️ Custom Function Registration
Register your own functions for use in QoQ queries.
Scalar Functions
Process a single value and return a single result:
Aggregate Functions
Process multiple values and return a single result:
📐 Operators
BoxLang QoQ supports all standard SQL operators plus bitwise operations.
Comparison Operators
Available: =, !=, <>, <, >, <=, >=, IS, IS NOT, LIKE, NOT LIKE, IN, NOT IN, BETWEEN, NOT BETWEEN
Mathematical Operators
Available: +, -, *, /, % (modulo)
Bitwise Operators
Available: & (AND), | (OR), ^ (XOR), ! (NOT)
String Concatenation
Available: || (concatenation)
🎚️ Query Clauses
DISTINCT
Remove duplicate rows:
WHERE
Filter rows:
GROUP BY
Aggregate data:
ORDER BY
Sort results:
TOP and LIMIT
Limit result count:
UNION
Combine multiple queries:
🎯 Advanced Examples
Data Transformation Pipeline
Complex Filtering
Pivot-like Operations
Data Deduplication
💡 Best Practices
Performance
✅ Use JOINs over subqueries when possible for better performance
✅ Filter early - Apply WHERE clauses to reduce row count before JOINs
✅ Limit columns - SELECT only needed columns, not SELECT *
✅ Use indexes - Original database query results maintain index information
✅ Minimize DISTINCT - Use only when necessary as it requires deduplication
Memory Management
✅ Limit result sets - Use TOP/LIMIT to prevent memory issues
✅ Process in batches - For large datasets, break into smaller QoQ operations
✅ Clean up queries - Remove references to large query objects when done
✅ Monitor query size - Be aware of result set row counts and column widths
Code Quality
✅ Use parameterized queries - Prevent SQL injection even in QoQ
✅ Alias tables - Always use table aliases for clarity and readability
✅ Format SQL - Use proper indentation and line breaks
✅ Document complex logic - Comment non-obvious CASE statements and subqueries
✅ Test edge cases - Verify NULL handling, empty results, and data type conversions
Data Integrity
✅ Preserve types - QoQ maintains original column data types
✅ Handle NULLs - Use COALESCE or ISNULL for NULL-safe operations
✅ Validate joins - Ensure JOIN conditions match appropriate data types
✅ Check for duplicates - Use DISTINCT when necessary
🚫 Common Pitfalls
❌ Forgetting dbtype option
❌ Ambiguous column references with multiple tables
❌ Not handling NULL values
❌ Using correlated subqueries
🔍 Limitations
Query of Queries has some limitations to be aware of:
No correlated subqueries - Subqueries cannot reference outer query tables
No window functions - OVER(), PARTITION BY not supported
No CTEs - Common Table Expressions (WITH clause) not available
Read-only - Cannot INSERT, UPDATE, or DELETE rows
No transactions - All operations are immediate
In-memory only - Large result sets may impact memory usage
🔗 Related Documentation
Querying - Execute database queries
Datasources - Configure database connections
Query Type Reference - Query object methods and properties
queryExecute() BIF - Complete BIF reference
📚 Additional Resources
SQLite SQL Syntax - BoxLang QoQ grammar is based on SQLite
Last updated
Was this helpful?
