Intermediate PostgreSQL

Creating and Using Views in PostgreSQL

Simplify complex queries by saving them as reusable views, including materialized views.

5 min read Tutorial

A view is a named query stored in the database. It acts like a virtual table that you can SELECT from, simplifying complex joins and providing a clean interface for application code.

Creating a View

CREATE VIEW customer_orders AS
SELECT
  c.id AS customer_id,
  c.first_name,
  c.last_name,
  c.email,
  COUNT(o.id) AS order_count,
  COALESCE(SUM(o.total), 0) AS total_spent
FROM customers c
LEFT JOIN orders o ON c.id = o.customer_id
GROUP BY c.id, c.first_name, c.last_name, c.email;

-- Use it like a regular table
SELECT * FROM customer_orders
WHERE total_spent > 500
ORDER BY total_spent DESC;

The query inside the view runs every time you SELECT from it. The view itself stores no data -- it is simply a saved SQL definition.

Updating and Dropping Views

-- Replace an existing view
CREATE OR REPLACE VIEW customer_orders AS
SELECT
  c.id AS customer_id,
  c.first_name || ' ' || c.last_name AS full_name,
  COUNT(o.id) AS order_count,
  COALESCE(SUM(o.total), 0) AS total_spent
FROM customers c
LEFT JOIN orders o ON c.id = o.customer_id
GROUP BY c.id, c.first_name, c.last_name;

-- Drop a view
DROP VIEW IF EXISTS customer_orders;

Materialized Views

-- Materialized view stores the result on disk
CREATE MATERIALIZED VIEW monthly_revenue AS
SELECT
  DATE_TRUNC('month', created_at) AS month,
  SUM(total) AS revenue,
  COUNT(*) AS order_count
FROM orders
GROUP BY DATE_TRUNC('month', created_at)
ORDER BY month;

-- Query it (fast, reads cached data)
SELECT * FROM monthly_revenue;

-- Refresh when underlying data changes
REFRESH MATERIALIZED VIEW monthly_revenue;

-- Refresh without locking reads
REFRESH MATERIALIZED VIEW CONCURRENTLY monthly_revenue;

Unlike regular views, materialized views store computed results on disk. They are much faster to query but must be refreshed manually. Use CONCURRENTLY to refresh without blocking reads (requires a unique index on the view).

When to Use Views

  • Regular views -- to simplify complex joins and provide a clean API for application queries
  • Materialized views -- for expensive aggregations that do not need real-time data (dashboards, reports)
  • To restrict column access by exposing only certain fields to specific roles
  • To maintain backward compatibility when refactoring table structures

Try this query in UnifySQL

Write, optimize, and collaborate on PostgreSQL queries with AI assistance.

Start Free