January 17, 2025
Read time: About 7 minutes
Loading... views

BẢNG TẠM POSTGRES (PostgreSQL common table expression)

BẢNG TẠM POSTGRES (PostgreSQL common table expression)

  1. Giới thiệu

Biểu thức bảng chung (common table expression) cho phép ta tạo một tập kết quả tạm thời với query.

No giúp ta tạo các truy vấn phức tạp một cách dễ hiểu và có tổ chức hơn. Nó được sử dụng để định nghĩa một bảng tạm thời trong phạm vi của một truy vấn SELECT, INSERT, UPDATE, hoặc DELETE.

2. Tại sao cần CTE?

3. Cấu trúc của một CTE


WITH cte_name (column1, column2, ...) AS (

-- CTE query

SELECT ...

)

-- Main query using the CTE

SELECT ...

FROM cte_name;

4. Cte example

WITH action_films AS (
SELECT
f.title,
f.length
FROM
film f
INNER JOIN film_category fc USING (film_id)
INNER JOIN category c USING(category_id)
WHERE
c.name = 'Action'
)
SELECT \* FROM action_films;

Kết quả:

Ví dụ kết một bảng thường với một CTE:


WITH cte_rental AS (

SELECT

staff_id,

COUNT(rental_id) rental_count

FROM

rental

GROUP BY

staff_id

)

SELECT

s.staff_id,

first_name,

last_name,

rental_count

FROM

staff s

INNER JOIN cte_rental USING (staff_id);

Câu query trên sẽ lấy ra liệt kê số film được mượn ứng với mỗi staff

Tiếp đến, ta join bảng staff với CTE trên để lấy ra thông tin chi tiết của mỗi staff:

Ví dụ dùng query với nhiều CTE cùng lúc:


WITH film_stats AS (

-- CTE 1: Calculate film statistics

SELECT

AVG(rental_rate) AS avg_rental_rate,

MAX(length) AS max_length,

MIN(length) AS min_length

FROM film

),

customer_stats AS (

-- CTE 2: Calculate customer statistics

SELECT

COUNT(DISTINCT customer_id) AS total_customers,

SUM(amount) AS total_payments

FROM payment

)

-- Main query using the CTEs

SELECT

ROUND((SELECT avg_rental_rate FROM film_stats), 2) AS avg_film_rental_rate,

(SELECT max_length FROM film_stats) AS max_film_length,

(SELECT min_length FROM film_stats) AS min_film_length,

(SELECT total_customers FROM customer_stats) AS total_customers,

(SELECT total_payments FROM customer_stats) AS total_payments;

Câu query này sẽ như sau: lấy ra thống kê về film bỏ vào cte film_stats (đánh giá phim trung bình, độ dài phim dài nhất, độ dài phim ngắn nhất) và lấy ra thống kê về khách hàng bỏ vào cte customer_stats (tổng lượng customer, tổng doanh thu) => sau đó sẽ gom chung vào 1 query select để lấy ra cùng lúc thống kê film và customer:

Vậy nếu ta viết query tương tự như trên bằng query thuần thì sao?

EXPLAIN (ANALYZE, BUFFERS ) SELECT

ROUND(film_stats.avg_rental_rate, 2) AS avg_film_rental_rate,

film_stats.max_length,

film_stats.min_length,

customer_stats.total_customers,

customer_stats.total_payments

FROM

(SELECT

AVG(rental_rate) AS avg_rental_rate,

MAX(length) AS max_length,

MIN(length) AS min_length

FROM film) AS film_stats,

(SELECT

COUNT(DISTINCT customer_id) AS total_customers,

SUM(amount) AS total_payments

FROM payment) AS customer_stats;

Performence thì thế nào:

Có thể thấy performence giữa chúng gần như tương đương với dùng cte:

5. CTE Recursive

Giống như đệ quy trong lập trình bình thường, ta có thể sử dụng CTE Recursive để tạo một query đệ quy với từ khóa WITH RECURSIVE


WITH RECURSIVE cte_name (column1, column2, ...)

AS(

-- anchor member

SELECT select_list FROM table1 WHERE condition

UNION \[ALL\]

-- recursive term

SELECT select_list FROM cte_name WHERE recursive_condition

)

SELECT * FROM cte_name;

Ta sẽ tạo một bảng employee:


CREATE TABLE employees (

employee_id SERIAL PRIMARY KEY,

full_name VARCHAR NOT NULL,

manager_id INT

);

Ta sẽ viết câu query đệ quy lấy ra list tất cả các employee là cấp dưới của employee có id = 2 (tức là B thuộc quản lý của A, C thuộc quản lý của B => B, C đều là cấp dưới của A)


WITH RECURSIVE subordinates AS (

SELECT

employee_id,

manager_id,

full_name

FROM

employees

WHERE

employee_id = 2

UNION

SELECT

e.employee_id,

e.manager_id,

e.full_name

FROM

employees e

INNER JOIN subordinates s ON s.employee_id = e.manager_id

)

SELECT * FROM subordinates;

6. Ưu Điểm của CTE

7. Nhược Điểm của CTE

8. So Sánh CTE với Các Phương Pháp Khác

9. Kết Luận

CTE trong PostgreSQL là một công cụ mạnh mẽ để giúp truy vấn dữ liệu phức tạp trở nên rõ ràng và dễ bảo trì hơn. Nó đặc biệt hữu ích cho việc tổ chức các truy vấn phức tạp và thực hiện các bài toán đệ quy. Tuy nhiên, việc sử dụng CTE cũng cần cân nhắc về hiệu suất và quy mô dữ liệu để tối ưu cho từng trường hợp.

10. Minh Họa Cuối Cùng

Để minh họa rõ hơn, chúng ta có thể xem CTE giống như một tập hợp các công thức tính toán trong bảng tính. Bạn định nghĩa các bước nhỏ (CTE) để dễ kiểm soát, sau đó dùng chúng để tính kết quả cuối cùng, làm cho mọi thứ trở nên đơn giản hơn so với viết toàn bộ phép tính trong một bước dài và khó đọc.

About this Post

This post is written by haphuthinh, licensed under CC BY-NC 4.0.

#backend#postgresql#database

Recommended Posts

Bạn thấy khuyến nghị này thế nào?