DEV Community

Cover image for Views in PostgreSQL: A Complete Guide with Examples
Arnav Sharma
Arnav Sharma

Posted on

Views in PostgreSQL: A Complete Guide with Examples

When working with relational databases like PostgreSQL, you often need to simplify complex queries, enforce data security, or speed up reporting. That’s where Views come in.

A view is essentially a virtual table defined by a query. Instead of writing the same complex query again and again, you save it as a view and query it like a table.

In this blog, we’ll explore the different types of views in PostgreSQL, their use cases, pros and cons, examples, and best practices.


🏷️ Types of Views in PostgreSQL


1. Simple View

📌 What is it?

A view built from a single table without joins or aggregations.

Why use it?

  • Hide unnecessary columns
  • Simplify queries
  • Enforce limited access
CREATE TABLE employees (
    id SERIAL PRIMARY KEY,
    name TEXT,
    department TEXT,
    salary NUMERIC,
    active BOOLEAN
);

-- Simple view showing only basic employee info
CREATE VIEW employee_public_info AS
SELECT id, name, department
FROM employees;

SELECT * FROM employee_public_info;

Enter fullscreen mode Exit fullscreen mode

⚖️ Pros: Lightweight, updatable, always real-time

⚖️ Cons: Doesn’t reduce computation cost


2. Complex View

📌 What is it?

A view involving joins, group by, or aggregates.

Why use it?

  • Simplify reporting queries

  • Centralize business logic

CREATE TABLE sales (
    id SERIAL PRIMARY KEY,
    employee_id INT,
    amount NUMERIC,
    sale_date DATE
);

-- Complex view: total sales per department
CREATE VIEW department_sales AS
SELECT e.department, SUM(s.amount) AS total_sales
FROM employees e
JOIN sales s ON e.id = s.employee_id
GROUP BY e.department;

SELECT * FROM department_sales;

Enter fullscreen mode Exit fullscreen mode

⚖️ Pros: Great for dashboards, reduces repeated SQL code

⚖️ Cons: Usually not updatable, may be slow on large datasets


3. Materialized View

📌 What is it?

A pre-computed, stored result set of a query. Unlike normal views, it stores data on disk.

Why use it?

  • Speed up expensive queries

  • Power analytics dashboards

CREATE MATERIALIZED VIEW monthly_sales AS
SELECT DATE_TRUNC('month', sale_date) AS month,
       SUM(amount) AS total
FROM sales
GROUP BY DATE_TRUNC('month', sale_date);

-- Refresh when new data arrives
REFRESH MATERIALIZED VIEW monthly_sales;

SELECT * FROM monthly_sales ORDER BY month;

Enter fullscreen mode Exit fullscreen mode

⚖️ Pros: Huge performance boost, can be indexed

⚖️ Cons: Data can get stale, needs manual refresh


4. Updatable View

📌 What is it?

A view where you can INSERT, UPDATE, DELETE rows directly.

Why use it?

  • Provide restricted updates without exposing full table
-- Only active employees
CREATE VIEW active_employees AS
SELECT *
FROM employees
WHERE active = true;

-- Update via the view
UPDATE active_employees SET active = false WHERE id = 3;

Enter fullscreen mode Exit fullscreen mode

⚖️ Pros: Secure way to allow controlled updates

⚖️ Cons: Works only with simple queries


5. Read-Only View

📌 What is it?

A view that cannot be updated (complex logic, joins, or aggregates).

Why use it?

  • Safely expose analytics reports
-- Employees with high sales
CREATE VIEW top_performers AS
SELECT employee_id, SUM(amount) AS total_sales
FROM sales
GROUP BY employee_id
HAVING SUM(amount) > 50000;

SELECT * FROM top_performers;

Enter fullscreen mode Exit fullscreen mode

⚖️ Pros: Safe for reporting

⚖️ Cons: Can’t modify data through it


6. Recursive View

📌 What is it?

A view built using a recursive CTE to handle hierarchies.

Why use it?

  • Org charts, folder structures, category trees
-- Hierarchy of employees and managers
CREATE VIEW employee_hierarchy AS
WITH RECURSIVE emp_cte AS (
    SELECT id, name, manager_id
    FROM employees
    WHERE manager_id IS NULL
    UNION ALL
    SELECT e.id, e.name, e.manager_id
    FROM employees e
    JOIN emp_cte c ON e.manager_id = c.id
)
SELECT * FROM emp_cte;

SELECT * FROM employee_hierarchy;

Enter fullscreen mode Exit fullscreen mode

⚖️ Pros: Perfect for recursive data

⚖️ Cons: Can get slow for deep hierarchies


🛒 Real-World Example: Views in an E-commerce App

Imagine you’re building an e-commerce platform. Here’s how different views fit in:

  • Simple Viewcustomer_directory (hide sensitive columns)

  • Complex Viewcategory_revenue (total revenue per category)

  • Materialized Viewdaily_sales (fast dashboards with precomputed data)

  • Updatable Viewactive_products (only allow editing active products)

  • Read-Only Viewtop_customers (find VIPs safely)

  • Recursive Viewcategory_hierarchy (nested categories navigation)

By mixing these types, your database becomes secure, performant, and easy to query.


⚡ Performance Best Practices

  1. Index Materialized Views

    CREATE UNIQUE INDEX idx_daily_sales_date ON daily_sales(order_date);
    
    
  2. Refresh Strategy

-   Refresh materialized views with `REFRESH MATERIALIZED VIEW` at scheduled times (e.g., nightly with `pg_cron`).
Enter fullscreen mode Exit fullscreen mode
  1. Optimize Complex Views
-   Break into smaller views or switch to materialized views if performance is bad.
Enter fullscreen mode Exit fullscreen mode
  1. Use WITH CHECK OPTION for updatable views

    CREATE VIEW active_products AS
    SELECT * FROM products WHERE is_active = true
    WITH CHECK OPTION;
    
    
  2. Recursive Views: Add Depth Limit

    WHERE p.depth < 10;
    
    

🏆 Key Takeaways

  • Use simple & complex views for query simplification and security.

  • Use materialized views for performance-heavy reporting.

  • Use updatable views with care.

  • Use recursive views for hierarchical data.

  • Always balance freshness vs performance.

With the right type of view, you can make your PostgreSQL database faster, safer, and easier to work with 🚀

Top comments (0)