Building a Dynamic Parameterized Query UI for ClickHouse
- LK Rajat
- Jul 3
- 4 min read
A task which was a part of Clickhouse's Intern Tasks 2024/2025. link to repository: https://github.com/rajatmohan22/ClickHouseUI
Introduction
As part of ClickHouse’s 2024-25 intern program, I set out to build ClickHouseUI—a lightweight, full-stack application that empowers users to explore their ClickHouse data interactively, without ever writing raw SQL. In this deep-dive blog, I’ll walk you through the motivations, architecture, key features, challenges overcome, and lessons learned across both frontend and backend.
Whether you’re an analyst looking for a slick way to slice and dice your tables or a developer aiming to scaffold your own data-exploration tooling, you’ll find insights and patterns that you can reapply to your own ClickHouse integrations.
Why ClickHouseUI?
Democratize Data AccessNot every stakeholder is fluent in SQL. ClickHouseUI bridges that gap by offering button-driven filters, grouping, sorting, and charting.
Leverage ClickHouse’s StrengthsFrom interactive ad-hoc queries to lightning-fast analytical workloads, ClickHouse excels at sub-second response times on large datasets. ClickHouseUI surfaces that power in a friendly interface.
Rapid PrototypingInterns and developers alike can spin up a working UI in under an hour and iterate through new features in minutes
Project Goals
Schema Discovery
List databases and tables dynamically via ClickHouse’s HTTP API.
Parameterized Query Builder
Compose filters, sorts, group-bys, aggregates, and date ranges through intuitive controls.
AI-Powered Suggestions
Offer click-to-run descriptive-statistic queries (powered by OpenAI) based on your schema.
Smart Charting
One-click renderings: histograms, bar/line/pie charts, scatter plots, bubble maps.
Modular & Extensible
Clean separation: EJS templates + vanilla JS on the frontend; Express routes on the backend.
Architecture Overview
Frontend
Templating: EJS for server-rendered pages, with Bootstrap for layout.
State Management: All “blocks” (Filter, Sort, Group, Aggregate, Date Range, Select Columns) live in a queryBlocks[] array.
Dynamic Controls:
Buttons wired to functions like addFilter(), addGroup(), etc.
Each injection uses a reusable createDropdown(label, controls[]) helper to maintain consistent Bootstrap grid alignment.
Query Submission:
showQueryResult() serializes each block into JSON (e.g. {type:"Filter",column:"age",value:"30"}) and POSTs to /param.
AI & Charts:
/ai suggestions spawn quick-run SQL buttons.
Chart buttons build small forms (X/Y axes, aggregation) and POST to /chart, rendering Chart.js configs on a <canvas>.
Backend
Express Server with JSON-body parsing.
ClickHouse HTTP: Raw SQL sent over HTTP POST, with FORMAT TabSeparatedWithNames for tabular results.
Parameterized Query Route (/param)
Select Columns: Honors an explicit multiselect block if present.
Filter / Date Range: Translates blocks into WHERE clauses using column = 'value' or column BETWEEN toDateTime('start') AND toDateTime('end').
Group / Aggregate: Collects GROUP BY keys and FUNC(column) AS alias parts.
Sort By: Appends an ORDER BY clause.
Fallback: If no explicit selections or groupings, does SELECT *.
Chart Route (/chart)
Builds tailor-made aggregations per chart type (e.g. heatmap ⇒ two-dimensional aggregation).
Returns a Chart.js config object for immediate rendering.
Key Features & Intern Milestones
Dynamic Schema Fetching
Intern Task: Hooked into ClickHouse’s SHOW DATABASES and SHOW TABLES IN db via HTTP, then populated <select>s on the fly.
WYSIWYG Query Blocks
Built a composable query-builder area, where each new block visually represents part of the SQL.
Implemented “Undo” & “Clear” actions to remove or reset blocks.
Date Range Without Flatpickr
Swapped out a heavy date-picker library for native <input type="date"> controls + “Last 7/30/90 days” presets—keeping the bundle lightweight.
Select Columns Multiselect
Added a multiselect control that injects a Select Columns block; backend honors that by overriding SELECT *.
AI-Driven Descriptive Statistics
Leveraged OpenAI’s GPT models to suggest 10 common analytics questions (e.g. “Average order value by day”), converting them to one-click SQL and UI buttons.
Chart.js Integration
Mapped each chart type to a SQL pattern (e.g. GROUP BY xAxis) and transformed ClickHouse’s tabular output into Chart.js JSON configs for bar, line, pie, scatter, heatmap, and radar.
Challenges & Solutions
“Not under aggregate” Errors
ClickHouse requires that any non-aggregated column in a SELECT appear in your GROUP BY. We solved this by dynamically building the GROUP BY clause from the user’s Group/Select blocks, and falling back to SELECT * only when no grouping/aggregation was used.
Date Range Validation
Ensured users can’t submit an incomplete date-range block—added frontend alerts (“Please choose both start & end dates”) and backend guards before SQL assembly.
Dynamic Column Types
Abstracted all column metadata fetches so any table schema (numbers, strings, datetimes) seamlessly populates filters, axes selectors, and multiselects.
Looking Ahead
Role-Based Views: Show/hide certain analytics features based on user permissions.
Advanced Charts: Add box-plots and heatmaps via Chart.js plugins.
Custom SQL Blocks: Let power users inject raw SQL snippets safely.
Caching & Pagination: For extremely large tables, add lazy loading and result caching.
Conclusion
ClickHouseUI crystallizes how intern-built tooling can harness ClickHouse’s raw power and expose it through a polished, button-driven interface. From zero to a fully parameterized query-and-chart system in weeks, this project demonstrates:
Speed of Development with Express, EJS, and vanilla JS.
Scalability of ClickHouse’s HTTP API for both tabular and JSON output.
Extensibility, thanks to a modular block architecture and clear separation of concerns.
If you’re embarking on your own ClickHouse integration, take inspiration from this intern project: start small, iterate fast, and let the database’s speed do the heavy lifting.
— Built during ClickHouse’s Intern Tasks 2024.
Comments