What is a view, and why would you create one?
A view is a named query. When you reference it, the database runs the query it stands for and returns the result as though it were a table. Nothing is stored: the view holds SQL, not data.
CREATE TABLE customers (
id INTEGER PRIMARY KEY,
name VARCHAR(120) NOT NULL,
city VARCHAR(80) NOT NULL
);
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
customer_id INTEGER NOT NULL,
amount DECIMAL(10, 2) NOT NULL,
status VARCHAR(20) NOT NULL
);
INSERT INTO customers (id, name, city) VALUES
(1, 'Ada Lovelace', 'London'),
(2, 'Grace Hopper', 'New York'),
(3, 'Alan Turing', 'London');
INSERT INTO orders (id, customer_id, amount, status) VALUES
(1, 1, 120.00, 'shipped'),
(2, 1, 340.50, 'pending'),
(3, 2, 75.25, 'shipped');
CREATE VIEW customer_summary AS
SELECT c.id AS customer_id,
c.name AS customer_name,
c.city,
COUNT(o.id) AS order_count,
ROUND(COALESCE(SUM(o.amount), 0), 2) AS total_spend
FROM customers AS c
LEFT JOIN orders AS o ON o.customer_id = c.id
GROUP BY c.id, c.name, c.city;
SELECT customer_id, customer_name, city, order_count, total_spend
FROM customer_summary
ORDER BY customer_id;Three rows come back, each with the customer's details and their order totals already worked out. Alan Turing shows 0 orders and a total of 0.00, because the LEFT JOIN kept him in the result and the COALESCE turned his NULL sum into a zero.
Four reasons to create one. To name a piece of business logic once and reuse it, so the definition of "customer spend" lives in one place. To hide the shape of the tables from the consumers of a report, so a change to the schema does not break every query that reads it. To give a stable interface to a set of tables that several teams read. And to express a permission boundary — a view that exposes three columns of a table can be granted to a reporting user without granting them the table.
Two limitations to remember. A view is not a materialised result, so a query against a view over a large table costs exactly what the underlying query would have cost — with one caveat, that some engines will refuse to push a predicate from the outer query into the view, which can make a view slower than writing the query inline. And a view that aggregates cannot generally be updated through.