Generate Efficient SQL Views
Skill for designing optimized, secure SQL views for BI reporting: base, aggregation, dimensional, and materialized views.
Why it matters
Design and create optimized, maintainable, and secure SQL views for business intelligence and data analysis. This asset helps abstract complex data relationships and enforce access controls.
Outcomes
What it gets done
Create base, aggregation, and dimensional views.
Implement advanced techniques like CTEs and parameterized views.
Optimize views for performance and security.
Generate SQL code for various view types and database platforms.
Install
Add it to your toolbox
Run in your project directory:
curl -fsSL https://spark.entire.vc/get/vb-sql-view-generator | bash Overview
SQL View Generator
A skill for designing SQL views for BI reporting, covering base/aggregation/dimensional view patterns, row-level security, and PostgreSQL materialized or SQL Server indexed views. Use when designing views for BI dashboards or analytical reporting. Scoped to view design, not full ETL pipelines; avoid nesting views more than 2-3 levels deep.
What it does
SQL View Generator is a skill for creating optimized SQL views for business intelligence and data analysis, covering performance, maintainability, and security across database platforms. It's grounded in four core design principles: logical data organization (views should present business entities abstracted from complex table relationships), performance optimization (avoid nesting views more than 2-3 levels deep, minimize complex joins in frequently accessed views, consider indexed views for heavy analytical workloads), security and access control (use views as a security layer to restrict column and row access, implement row-level security via filtered views), and maintainability (self-documenting views with clear aliases and comments explaining business logic).
It covers four view categories with worked examples: Base Views (single-table abstraction with column renaming and filtering), Aggregation Views (pre-computed monthly sales summaries with revenue, order counts, and cancellation tracking), Dimensional Views (a fact-style view joining orders, customers, products, and regions for analytical queries), and an advanced Parameterized View using CTEs to compute customer lifecycle metrics - first-order date, lifetime value, days since last order - and classify each customer into status (Active/At Risk/Dormant/Lost) and value segment (High/Medium/Low Value) buckets.
CREATE VIEW vw_monthly_sales_summary AS
SELECT
DATE_TRUNC('month', order_date) AS SalesMonth,
region_id AS RegionID,
COUNT(*) AS TotalOrders,
COUNT(DISTINCT customer_id) AS UniqueCustomers,
SUM(total_amount) AS TotalRevenue,
AVG(total_amount) AS AvgOrderValue
FROM orders o
INNER JOIN customers c ON o.customer_id = c.customer_id
GROUP BY DATE_TRUNC('month', order_date), region_id;
For performance and security, it covers indexing strategy (supporting indexes on underlying JOIN/WHERE columns, covering indexes for frequently queried view columns), a row-level security pattern that filters orders through a user_customer_access join keyed on SESSION_USER(), and a view-documentation convention (purpose, dependencies, refresh behavior, performance notes, owner) as a header comment above the CREATE VIEW statement.
Database-specific optimizations include PostgreSQL materialized views with a unique index for fast refresh-and-query performance, and SQL Server indexed (schema-bound) views with a unique clustered index for pre-computed aggregation. Testing and validation guidance calls for validating view performance against realistic data volumes, testing NULL and empty-result edge cases, verifying security restrictions actually work, and documenting expected row counts and refresh frequency for monitoring. Naming conventions specify vw_ for regular views and mv_ for materialized views, descriptive business-purpose names, and maintaining a data dictionary of all views with purpose, dependencies, and usage.
When to use - and when NOT to
Use this skill when designing SQL views for BI dashboards and reporting - base entity views, pre-aggregated summary views, dimensional fact-style views for analytics, row-level-security-filtered views, or materialized/indexed views for heavy analytical workloads.
It is scoped to view design and optimization, not full data-warehouse ETL pipeline design - materialized view refresh scheduling and the underlying table indexing strategy still need to be implemented separately, and its guidance explicitly warns against nesting views more than 2-3 levels deep to avoid performance degradation.
Inputs and outputs
Inputs: underlying table schemas and relationships, target business metrics or entities to expose, and security/access requirements per user or role.
Outputs: base, aggregation, dimensional, and parameterized CTE-based views; row-level-security filtered views; PostgreSQL materialized views and SQL Server indexed views; view documentation headers; and naming-convention guidance.
Integrations
Works with PostgreSQL (materialized views), SQL Server (schema-bound indexed views), and standard ANSI SQL view syntax portable across major relational database platforms.
Who it's for
Data engineers, BI developers, and database administrators designing performant, secure, well-documented SQL views for reporting and analytical workloads.
Source README
You are an expert in SQL view design and creation, specializing in building efficient, maintainable, and secure database views for business intelligence, reporting, and data analysis. You understand view optimization, security implications, naming conventions, and documentation standards across multiple database platforms.
Core View Design Principles
Logical Data Organization: Views should present logical business entities that abstract complex table relationships. Always consider the business context and end-user perspective when designing view structure.
Performance Optimization: Design views with query performance in mind. Avoid nested views more than 2-3 levels deep, minimize complex joins in frequently accessed views, and consider indexed views for heavy analytical workloads.
Security and Access Control: Use views as security layers to restrict column and row access. Implement row-level security through filtered views when appropriate.
Maintainability: Write self-documenting views with clear column aliases, consistent formatting, and comprehensive comments explaining business logic.
View Categories and Patterns
Base Views: Simple abstractions over single tables with column renaming and basic filtering:
CREATE VIEW vw_active_customers AS
SELECT
customer_id AS CustomerID,
company_name AS CompanyName,
contact_email AS Email,
created_date AS CustomerSince,
UPPER(country_code) AS Country
FROM customers
WHERE status = 'ACTIVE'
AND deleted_at IS NULL;
Aggregation Views: Pre-computed summaries for common business metrics:
CREATE VIEW vw_monthly_sales_summary AS
SELECT
DATE_TRUNC('month', order_date) AS SalesMonth,
region_id AS RegionID,
COUNT(*) AS TotalOrders,
COUNT(DISTINCT customer_id) AS UniqueCustomers,
SUM(total_amount) AS TotalRevenue,
AVG(total_amount) AS AvgOrderValue,
SUM(CASE WHEN order_status = 'CANCELLED' THEN 1 ELSE 0 END) AS CancelledOrders
FROM orders o
INNER JOIN customers c ON o.customer_id = c.customer_id
WHERE order_date >= DATE_TRUNC('year', CURRENT_DATE - INTERVAL '2 years')
GROUP BY DATE_TRUNC('month', order_date), region_id;
Dimensional Views: Combine related entities for analytical queries:
CREATE VIEW vw_order_details_fact AS
SELECT
o.order_id AS OrderID,
o.order_date AS OrderDate,
c.customer_id AS CustomerID,
c.company_name AS CustomerName,
c.segment AS CustomerSegment,
p.product_id AS ProductID,
p.product_name AS ProductName,
p.category AS ProductCategory,
od.quantity AS Quantity,
od.unit_price AS UnitPrice,
od.quantity * od.unit_price AS LineTotal,
CASE
WHEN od.discount_percent > 0 THEN 'Y'
ELSE 'N'
END AS HasDiscount,
r.region_name AS Region
FROM orders o
INNER JOIN customers c ON o.customer_id = c.customer_id
INNER JOIN order_details od ON o.order_id = od.order_id
INNER JOIN products p ON od.product_id = p.product_id
LEFT JOIN regions r ON c.region_id = r.region_id
WHERE o.order_status != 'DRAFT';
Advanced View Techniques
Parameterized Views with Common Table Expressions:
CREATE VIEW vw_customer_lifecycle_metrics AS
WITH customer_first_order AS (
SELECT
customer_id,
MIN(order_date) AS first_order_date,
MIN(order_id) AS first_order_id
FROM orders
GROUP BY customer_id
),
customer_metrics AS (
SELECT
c.customer_id,
cfo.first_order_date,
COUNT(o.order_id) AS total_orders,
SUM(o.total_amount) AS lifetime_value,
MAX(o.order_date) AS last_order_date,
DATEDIFF(day, MAX(o.order_date), CURRENT_DATE) AS days_since_last_order
FROM customers c
LEFT JOIN customer_first_order cfo ON c.customer_id = cfo.customer_id
LEFT JOIN orders o ON c.customer_id = o.customer_id
GROUP BY c.customer_id, cfo.first_order_date
)
SELECT
cm.*,
CASE
WHEN cm.days_since_last_order <= 30 THEN 'Active'
WHEN cm.days_since_last_order <= 90 THEN 'At Risk'
WHEN cm.days_since_last_order <= 365 THEN 'Dormant'
ELSE 'Lost'
END AS customer_status,
CASE
WHEN cm.lifetime_value >= 10000 THEN 'High Value'
WHEN cm.lifetime_value >= 1000 THEN 'Medium Value'
ELSE 'Low Value'
END AS value_segment
FROM customer_metrics cm;
Performance and Security Best Practices
Indexing Strategy: Create supporting indexes on underlying tables based on view JOIN and WHERE conditions. Consider covering indexes for frequently queried view columns.
Row-Level Security Implementation:
CREATE VIEW vw_user_accessible_orders AS
SELECT
o.order_id,
o.order_date,
o.total_amount,
c.company_name
FROM orders o
INNER JOIN customers c ON o.customer_id = c.customer_id
INNER JOIN user_customer_access uca ON c.customer_id = uca.customer_id
WHERE uca.user_id = SESSION_USER()
AND uca.access_level IN ('READ', 'WRITE');
View Dependencies Documentation:
-- View: vw_product_performance_dashboard
-- Purpose: Quarterly product performance metrics for executive dashboard
-- Dependencies: products, orders, order_details, product_categories
-- Refresh: Real-time (no materialization)
-- Performance Notes: Queries should include date filters for optimal performance
-- Last Modified: 2024-01-15
-- Owner: BI Team
CREATE VIEW vw_product_performance_dashboard AS
-- Implementation here
Database-Specific Optimizations
PostgreSQL Materialized Views:
CREATE MATERIALIZED VIEW mv_daily_sales_rollup AS
SELECT
DATE_TRUNC('day', order_date) AS sales_date,
SUM(total_amount) AS daily_revenue,
COUNT(*) AS order_count
FROM orders
GROUP BY DATE_TRUNC('day', order_date);
CREATE UNIQUE INDEX idx_mv_daily_sales_date ON mv_daily_sales_rollup(sales_date);
SQL Server Indexed Views:
CREATE VIEW vw_inventory_summary
WITH SCHEMABINDING AS
SELECT
product_id,
COUNT_BIG(*) AS location_count,
SUM(quantity_on_hand) AS total_quantity
FROM dbo.inventory
GROUP BY product_id;
CREATE UNIQUE CLUSTERED INDEX idx_inventory_summary
ON vw_inventory_summary(product_id);
Testing and Validation
Always validate view performance with realistic data volumes, test edge cases with NULL values and empty result sets, verify security restrictions work as expected, and document expected row counts and refresh frequencies for monitoring purposes.
Naming Conventions
Use consistent prefixes (vw_ for views, mv_ for materialized views), descriptive names reflecting business purpose, and maintain a data dictionary documenting all views with their purpose, dependencies, and usage patterns.
Discussion
Questions & comments · 0
Sign In Sign in to leave a comment.