CodeGym /Các khóa học /SQL SELF /Làm việc với mảng trong PostgreSQL

Làm việc với mảng trong PostgreSQL

SQL SELF
Mức độ, Bài học
Có sẵn

Làm việc với mảng trong PostgreSQL

Bây giờ tụi mình đã biết mấy cái cơ bản rồi, cùng đào sâu vào việc tạo mảng thực tế trong các truy vấn SQL nhé. Đây mới là phần thú vị nè!

Sử dụng constructor ARRAY[] trong SELECT

Constructor ARRAY[] cực kỳ tiện trong các truy vấn SELECT khi bạn muốn tạo mảng một cách rõ ràng. Kiểu như nói với PostgreSQL: “Ê, đây là mảng nè!”

-- Tạo mảng số
SELECT ARRAY[1, 2, 3, 4, 5] AS numbers;

-- Tạo mảng chuỗi
SELECT ARRAY['Thứ hai', 'Thứ ba', 'Thứ tư'] AS weekdays;

Lợi ích của ARRAY[] so với cú pháp {}

  1. Ép kiểu rõ ràng:
-- Với ARRAY[] bạn có thể chỉ định kiểu dữ liệu rõ ràng
SELECT ARRAY['2023-01-01'::DATE, '2023-12-31'::DATE] AS dates;

-- Với {} thì phải cẩn thận hơn
SELECT '{"2023-01-01", "2023-12-31"}'::DATE[] AS dates;
  1. Dễ đọc hơn trong các truy vấn phức tạp:
SELECT
product_name,
ARRAY[category, subcategory, brand] AS product_hierarchy
FROM products;

Ví dụ: tạo mảng số

Bắt đầu với kiểu kinh điển nha. Giả sử bạn cần tạo một mảng số:

SELECT ARRAY[1, 2, 3, 4, 5] AS my_array;

Kết quả sẽ như này:

my_array
{1,2,3,4,5}

Lưu ý: PostgreSQL trả về mảng theo format {} — đây chỉ là cách nó hiển thị mảng thôi. Nhìn hơi lạ nhưng quen nhanh lắm.

Ví dụ: tạo mảng chuỗi

Nếu bạn cần chuỗi thay vì số, chỉ cần thêm dấu nháy thôi:

SELECT ARRAY['tao', 'chuoi', 'cam'] AS fruits;

Kết quả:

fruits
{tao, chuoi, cam}

À mà, PostgreSQL thích làm mọi thứ đơn giản lắm. Dù bạn dùng ký tự Cyrillic hay bất kỳ bảng chữ cái nào khác, mảng vẫn chạy mượt mà luôn.

Ví dụ: mảng với dữ liệu kiểu khác (ví dụ, ngày tháng)

Vậy nếu tụi mình muốn nhét mảng ngày tháng thì sao? Dễ ẹc luôn:

SELECT ARRAY['2023-01-01'::DATE, '2023-12-31'::DATE] AS important_dates;

Kết quả:

important_dates
{2023-01-01, 2023-12-31}

Lưu ý cái ::DATE nha. Tụi mình nói rõ với PostgreSQL là kiểu dữ liệu DATE. Nếu không, nó sẽ lấy chuỗi luôn, mà như vậy thì không đúng lắm với ngày tháng đâu.

Tổng hợp dữ liệu thành mảng với array_agg()

Giờ chuyển qua phần nâng cao và thú vị hơn nè. Nếu bạn đã có bảng dữ liệu rồi, muốn gom nhóm thành mảng thì sao? Lúc này dùng function array_agg() là chuẩn bài.

Một trong những tính năng mạnh nhất — biến nhiều dòng thành mảng bằng array_agg().

Cách dùng cơ bản:

-- Tạo bảng test
CREATE TEMP TABLE students (
group_id INTEGER,
student_name TEXT
);

INSERT INTO students VALUES
(1, 'Anna'), (1, 'Otto'), (1, 'Maria'),
(2, 'Alex'), (2, 'Kira'),
(3, 'Elena');

-- Gom nhóm sinh viên theo group
SELECT
group_id,
array_agg(student_name) AS students
FROM students
GROUP BY group_id
ORDER BY group_id;

Sắp xếp phần tử trong mảng:

SELECT
group_id,
array_agg(student_name ORDER BY student_name) AS students_sorted
FROM students
GROUP BY group_id;

Lọc khi tổng hợp:

SELECT
group_id,
array_agg(student_name) FILTER (WHERE student_name LIKE 'A%') AS students_a
FROM students
GROUP BY group_id;

Ví dụ thực tế sử dụng

Mảng hữu ích trong nhiều tình huống hàng ngày: từ lưu trữ tags, quyền truy cập cho đến tổng hợp hành động người dùng trong ngày. Dưới đây là mấy ví dụ giúp bạn hiểu rõ hơn về cách dùng mảng trong PostgreSQL.

Ví dụ 1: Hệ thống tags cho blog

CREATE TABLE blog_posts (
    id SERIAL PRIMARY KEY,
    title TEXT NOT NULL,
    content TEXT,
    tags TEXT[]
);

-- Thêm dữ liệu với nhiều cú pháp khác nhau
INSERT INTO blog_posts (title, content, tags) VALUES
    ('Tim hieu PostgreSQL', 'Noi dung bai viet...',
     ARRAY['PostgreSQL', 'SQL', 'Co so du lieu']),
    ('Web phat trien nam 2024', 'Noi dung bai viet...',
     '{"JavaScript", "React", "Node.js"}'),
    ('May hoc', 'Noi dung bai viet...',
     ARRAY['ML', 'Python', 'Data Science']);

-- Tìm bài viết theo tag
SELECT title FROM blog_posts
WHERE 'PostgreSQL' = ANY(tags);

Ví dụ 2: Hệ thống quyền người dùng

CREATE TABLE users (
id SERIAL PRIMARY KEY,
username TEXT NOT NULL,
permissions TEXT[]
);

INSERT INTO users (username, permissions) VALUES
('admin', ARRAY['read', 'write', 'delete', 'manage_users']),
('editor', ARRAY['read', 'write']),
('viewer', ARRAY['read']);

-- Tổng hợp tất cả quyền duy nhất trong hệ thống
SELECT array_agg(DISTINCT permission) AS all_permissions
FROM users, unnest(permissions) AS permission;

Ví dụ 3: Lịch sử hành động người dùng

CREATE TABLE user_actions (
user_id INTEGER,
action TEXT,
action_date DATE
);

INSERT INTO user_actions VALUES
(1, 'dang nhap', '2024-01-01'),
(1, 'xem_trang_ca_nhan', '2024-01-01'),
(1, 'chinh_sua_cai_dat', '2024-01-01'),
(2, 'dang nhap', '2024-01-01'),
(2, 'dang xuat', '2024-01-01');

-- Gom nhóm hành động người dùng theo ngày
SELECT
user_id,
action_date,
array_agg(action ORDER BY action) AS daily_actions
FROM user_actions
GROUP BY user_id, action_date
ORDER BY user_id, action_date;

4. Truy vấn với mảng: chọn và lọc

Khi đã có mảng rồi thì phải biết cách lấy và phân tích nó chứ. Bạn có thể dùng SELECT bình thường để lấy mảng:

SELECT tags FROM articles WHERE id = 1;

Kết quả sẽ là:

tags
{SQL,PostgreSQL,Co so du lieu}

Nhưng nếu bạn muốn tìm bài viết có tag cụ thể, ví dụ PostgreSQL thì sao? Chủ đề này tụi mình sẽ nói kỹ ở bài sau, nhưng ý tưởng rất đơn giản: mảng cho bạn sự linh hoạt và có thể tìm giá trị bên trong mảng dễ dàng.

2
Nhiệm vụ
SQL SELF, mức độ, bài học
Đã khóa
Tạo bảng với mảng và truy vấn dữ liệu
Tạo bảng với mảng và truy vấn dữ liệu
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION