Giới thiệu
Để làm việc với dữ liệu trong cơ sở dữ liệu, bạn cần có khả năng truy xuất và nhắm mục tiêu các bản ghi cụ thể một cách hiệu quả. Bằng cách sử dụng các mệnh đề lọc trong các truy vấn của mình, bạn có thể thêm các tiêu chí cụ thể để chỉ trả lại các bản ghi có liên quan nhất.
Trong hướng dẫn này, chúng ta sẽ xem xét một số hoạt động lọc phổ biến nhất có sẵn trong PostgreSQL và trình bày cách sử dụng chúng để thu hẹp trọng tâm của các câu lệnh của bạn. Chúng tôi sẽ chỉ ra cách kiểm tra các đặc điểm trong các bản ghi riêng lẻ với WHERE
mệnh đề, cách nhóm các bản ghi lại với nhau để tóm tắt thông tin với GROUP BY
, cách lọc các nhóm bản ghi với HAVING
điều khoản phụ và cách đặt số lượng hàng trả về tối đa với LIMIT
mệnh đề.
Sử dụng WHERE
mệnh đề xác định tiêu chí đối sánh
Một trong những cách phổ biến và hữu ích nhất để chỉ ra các yêu cầu truy vấn của bạn là WHERE
mệnh đề. WHERE
mệnh đề cho phép bạn xác định tiêu chí tìm kiếm thực tế cho các câu lệnh truy vấn bằng cách chỉ định các điều kiện phải đúng cho tất cả các bản ghi phù hợp.
WHERE
mệnh đề hoạt động bằng cách xác định các biểu thức boolean được kiểm tra dựa trên mỗi hàng dữ liệu ứng viên. Nếu kết quả của biểu thức là false, hàng sẽ bị xóa khỏi kết quả và không được trả về hoặc tiếp tục đến giai đoạn xử lý tiếp theo. Nếu kết quả của biểu thức là true, nó đáp ứng các tiêu chí của tìm kiếm và sẽ tiếp tục được xử lý thêm với tư cách là một hàng ứng viên.
Cú pháp cơ bản của WHERE
mệnh đề giống như sau:
SELECT * FROM my_table WHERE <condition>;
<condition>
có thể là bất kỳ thứ gì dẫn đến giá trị boolean. Trong PostgreSQL, giá trị boolean là bất kỳ giá trị nào trong số TRUE
, FALSE
hoặc NULL
.
Các điều kiện thường được hình thành bằng cách sử dụng một hoặc nhiều toán tử sau:
-
=
:bằng -
>
:lớn hơn -
<
:nhỏ hơn -
>=
:lớn hơn hoặc bằng -
<=
:nhỏ hơn hoặc bằng -
<>
hoặc!=
:không bằng -
AND
:toán tử logic "và" - kết hợp hai điều kiện và trả vềTRUE
nếu cả hai điều kiện đềuTRUE
-
OR
:toán tử logic "hoặc" - kết hợp hai điều kiện và trả vềTRUE
nếu ít nhất một trong các điều kiệnTRUE
-
IN
:giá trị được chứa trong danh sách, chuỗi hoặc dải ô theo sau -
BETWEEN
:giá trị được chứa trong phạm vi các giá trị tối thiểu và tối đa theo sau, bao gồm cả -
IS NULL
:khớp nếu giá trị làNULL
-
NOT
:phủ định giá trị boolean theo sau -
EXISTS
:truy vấn theo sau chứa kết quả -
LIKE
:khớp với một mẫu (sử dụng các ký tự đại diện%
để khớp với 0 hoặc nhiều ký tự và_
để khớp với một ký tự) -
ILIKE
:khớp với một mẫu (sử dụng các ký tự đại diện%
để khớp với 0 hoặc nhiều ký tự và_
để khớp với một ký tự), không phân biệt chữ hoa chữ thường -
SIMILAR TO
:khớp với một mẫu sử dụng phương ngữ biểu thức chính quy của SQL -
~
:đối sánh với một mẫu sử dụng biểu thức chính quy POSIX, phân biệt chữ hoa chữ thường -
~*
:đối sánh với một mẫu sử dụng biểu thức chính quy POSIX, không phân biệt chữ hoa chữ thường -
!~
:không khớp với mẫu sử dụng biểu thức chính quy POSIX, phân biệt chữ hoa chữ thường -
!~*
:không khớp với mẫu sử dụng biểu thức chính quy POSIX, không phân biệt chữ hoa chữ thường
Trong khi danh sách trên đại diện cho một số cấu trúc kiểm tra phổ biến nhất, có nhiều toán tử khác mang lại kết quả boolean có thể được sử dụng cùng với WHERE
mệnh đề.
Ví dụ sử dụng WHERE
Một trong những cách kiểm tra đơn giản và phổ biến nhất là kiểm tra tính bình đẳng, sử dụng =
nhà điều hành. Tại đây, chúng tôi kiểm tra xem từng hàng trong customer
bảng có last_name
giá trị bằng Smith
:
SELECT * FROM customer WHERE last_name = 'Smith';
Chúng ta có thể thêm các điều kiện bổ sung vào điều này để tạo các biểu thức ghép bằng cách sử dụng các toán tử logic. Ví dụ này sử dụng AND
mệnh đề để thêm một bài kiểm tra bổ sung đối với first_name
cột. Các hàng hợp lệ phải thỏa mãn cả hai điều kiện đã cho:
SELECT * FROM customer WHERE first_name = 'John' AND last_name = 'Smith';
Tương tự, chúng ta có thể kiểm tra xem có đáp ứng bất kỳ điều kiện nào trong số một loạt điều kiện hay không. Tại đây, chúng tôi kiểm tra các hàng từ địa chỉ address
để xem liệu zip_code
giá trị bằng 60626 hoặc neighborhood
cột bằng chuỗi "Roger Park". Chúng tôi sử dụng hai dấu ngoặc kép đơn để chỉ ra rằng một dấu ngoặc kép theo nghĩa đen nên được tìm kiếm:
SELECT * FROM address WHERE zip_code = '60626' OR neighborhood = 'Roger''s Park';
IN
toán tử có thể hoạt động giống như một phép so sánh giữa một số giá trị, được bao bọc trong dấu ngoặc đơn. Nếu khớp với bất kỳ giá trị nào trong số các giá trị đã cho, biểu thức là TRUE
:
SELECT * FROM customer WHERE last_name IN ('Smith', 'Johnson', 'Fredrich');
Ở đây, chúng tôi kiểm tra một mẫu chuỗi bằng cách sử dụng LIKE
. %
hoạt động như một ký tự đại diện khớp với không hoặc nhiều ký tự, vì vậy "Pete", "Peter" và bất kỳ chuỗi nào khác bắt đầu bằng "Pete" sẽ khớp:
SELECT * FROM customer WHERE last_name LIKE 'Pete%';
Chúng tôi có thể thực hiện một tìm kiếm tương tự bằng cách sử dụng ~*
toán tử để kiểm tra các kết quả phù hợp bằng cách sử dụng biểu thức chính quy POSIX mà không phân biệt chữ hoa, chữ thường. Trong trường hợp này, chúng tôi kiểm tra xem giá trị của last_name
bắt đầu bằng "d" và chứa chuỗi con "on", sẽ khớp với các tên như "Dickson", "Donald" và "Devon":
SELECT * FROM customer WHERE last_name ~* '^D.*on.*';
Chúng tôi có thể kiểm tra xem một số đường phố có nằm trong khối 4000 địa chỉ hay không bằng cách sử dụng BETWEEN
và AND
toán tử để xác định một phạm vi bao gồm:
SELECT * FROM address WHERE street_number BETWEEN 4000 AND 4999;
Tại đây, chúng tôi có thể hiển thị bất kỳ customer
nào các mục nhập có số an sinh xã hội không dài 9 chữ số. Chúng tôi sử dụng LENGTH()
toán tử để lấy số chữ số trong trường và <>
để kiểm tra sự bất bình đẳng:
SELECT * FROM customer WHERE LENGTH(SSN) <> 9;
Sử dụng GROUP BY
mệnh đề tóm tắt nhiều bản ghi
GROUP BY
mệnh đề là một cách rất phổ biến khác để lọc kết quả bằng cách biểu diễn nhiều kết quả với một hàng duy nhất. Cú pháp cơ bản của GROUP BY
mệnh đề giống như sau:
SELECT <columns> FROM some_table GROUP BY <columns_to_group>
Khi một GROUP BY
mệnh đề được thêm vào một câu lệnh, nó yêu cầu PostgreSQL hiển thị một hàng cho mỗi giá trị duy nhất cho cột hoặc các cột đã cho. Điều này có một số ý nghĩa quan trọng.
Kể từ GROUP BY
mệnh đề là một cách biểu diễn nhiều hàng dưới dạng một hàng duy nhất, PostgreSQL chỉ có thể thực hiện truy vấn nếu nó có thể tính toán một giá trị cho mỗi cột mà nó có nhiệm vụ hiển thị. Điều này có nghĩa là mỗi cột được xác định bởi SELECT
một phần của câu lệnh phải là:
- được đưa vào
GROUP BY
để đảm bảo rằng mỗi hàng có một giá trị duy nhất - tóm tắt để tóm tắt tất cả các hàng trong mỗi nhóm
Thực tế mà nói, điều này có nghĩa là bất kỳ cột nào trong SELECT
danh sách không có trong GROUP BY
mệnh đề phải sử dụng một hàm tổng hợp để tạo ra một kết quả duy nhất cho cột cho mỗi nhóm.
Ví dụ sử dụng GROUP BY
Đối với các ví dụ trong phần này, giả sử rằng chúng ta có một bảng được gọi là pet
mà chúng tôi đã xác định và điền như vậy:
CREATE TABLE pet ( id SERIAL PRIMARY KEY, type TEXT, name TEXT, color TEXT, age INT);INSERT INTO pet (type, name, color, age) VALUES('dog', 'Spot', 'brown', 3),('dog', 'Rover', 'black', 7),('dog', 'Sally', 'brown', 1),('cat', 'Sabrina', 'black', 8),('cat', 'Felix', 'white', 4),('cat', 'Simon', 'orange', 8),('rabbit', 'Buttons', 'grey', 4),('rabbit', 'Bunny', 'brown', 8),('rabbit', 'Briony', 'brown', 6);
Cách sử dụng GROUP BY
đơn giản nhất là hiển thị phạm vi giá trị duy nhất cho một cột. Để làm như vậy, hãy sử dụng cùng một cột trong SELECT
và GROUP BY
. Tại đây, chúng ta thấy tất cả các màu được sử dụng trong bảng:
SELECT color FROM pet GROUP BY color;
color-------- black grey brown white orange(5 rows)
Khi bạn di chuyển ra ngoài một cột duy nhất trong SELECT
danh sách cột, bạn phải thêm các cột vào GROUP BY
mệnh đề hoặc sử dụng một hàm tổng hợp để tạo ra một giá trị duy nhất cho nhóm hàng đang được biểu diễn.
Ở đây, chúng tôi thêm type
vào GROUP BY
, nghĩa là mỗi hàng sẽ đại diện cho sự kết hợp duy nhất của type
và color
các giá trị. Chúng tôi cũng thêm age
, được tóm tắt bởi avg()
hàm để tìm tuổi trung bình của mỗi nhóm:
loạiSELECT type, color, avg(age) AS average_age FROM pet GROUP BY type, color;
type | color | average_age--------+--------+-------------------- rabbit | brown | 7.0000000000000000 cat | black | 8.0000000000000000 rabbit | grey | 4.0000000000000000 dog | black | 7.0000000000000000 dog | brown | 2.0000000000000000 cat | orange | 8.0000000000000000 cat | white | 4.0000000000000000(7 rows)
Các hàm tổng hợp cũng hoạt động tốt với một cột trong GROUP BY
mệnh đề. Ở đây, chúng tôi tìm thấy tuổi trung bình của từng loại động vật:
loạiSELECT type, avg(age) AS average_age FROM PET GROUP BY type;
type | average_age--------+-------------------- rabbit | 6.0000000000000000 dog | 3.6666666666666667 cat | 6.6666666666666667(3 rows)
Nếu chúng ta muốn hiển thị con cũ nhất của từng loại động vật, thay vào đó chúng ta có thể sử dụng max()
hàm trên age
cột. GROUP BY
mệnh đề thu gọn kết quả thành các hàng giống như trước đây, nhưng hàm mới sẽ thay đổi kết quả trong cột khác:
loạiSELECT type, max(age) AS oldest FROM pet GROUP BY type;
type | oldest--------+------- rabbit | 8 dog | 7 cat | 8(3 rows)
Sử dụng HAVING
mệnh đề lọc các nhóm bản ghi
GROUP BY
mệnh đề là một cách để tóm tắt dữ liệu bằng cách thu gọn nhiều bản ghi thành một hàng đại diện duy nhất. Nhưng nếu bạn muốn thu hẹp các nhóm này dựa trên các yếu tố bổ sung thì sao?
HAVING
mệnh đề là một bổ ngữ cho GROUP BY
cho phép bạn chỉ định các điều kiện mà mỗi nhóm phải đáp ứng để được đưa vào kết quả.
Cú pháp chung trông giống như sau:
SELECT <columns> FROM some_table GROUP BY <columns_to_group> HAVING <condition>
Thao tác này rất giống với WHERE
mệnh đề, với sự khác biệt là WHERE
lọc các bản ghi đơn lẻ và HAVING
lọc các nhóm bản ghi.
Ví dụ sử dụng HAVING
Sử dụng cùng một bảng mà chúng tôi đã giới thiệu trong phần trước, chúng tôi có thể chứng minh cách HAVING
mệnh đề hoạt động.
Ở đây, chúng tôi nhóm các hàng của pet
bảng theo các giá trị duy nhất trong loại address
, tìm giá trị nhỏ nhất của age
cũng. HAVING
sau đó, mệnh đề lọc kết quả để loại bỏ bất kỳ nhóm nào có độ tuổi không lớn hơn 1:
loạiSELECT type, min(age) AS youngest FROM pet GROUP BY type HAVING min(age) > 1;
type | youngest--------+---------- rabbit | 4 cat | 4(2 rows)
Trong ví dụ này, chúng tôi nhóm các hàng trong pet
bởi màu sắc của chúng. Sau đó, chúng tôi lọc các nhóm chỉ đại diện cho một hàng duy nhất. Kết quả cho chúng ta thấy mọi màu xuất hiện nhiều lần:
SELECT color FROM pet GROUP BY color HAVING count(color) > 1;
color------- black brown(2 rows)
Chúng tôi có thể thực hiện một truy vấn tương tự để nhận các kết hợp của type
và color
mà chỉ một loài động vật duy nhất có:
loạiSELECT type, color FROM pet GROUP BY type, color HAVING count(color) = 1;
type | color--------+-------- cat | black rabbit | grey dog | black cat | orange cat | white(5 rows)
Sử dụng LIMIT
mệnh đề đặt số lượng bản ghi tối đa
LIMIT
mệnh đề cung cấp một cách tiếp cận khác để phân tích các bản ghi mà truy vấn của bạn trả về. Thay vì loại bỏ các hàng dữ liệu dựa trên tiêu chí trong chính hàng đó, LIMIT
mệnh đề đặt số lượng bản ghi tối đa được trả về bởi một truy vấn.
Cú pháp cơ bản của LIMIT
trông như thế này:
SELECT * FROM my_table LIMIT <num_rows> [OFFSET <num_rows_to_skip>];
Đây, <num_rows>
cho biết số hàng tối đa để hiển thị từ truy vấn được thực thi. Điều này thường được sử dụng cùng với ORDER BY
mệnh đề để nhận các hàng có giá trị lớn nhất trong một cột nhất định. Ví dụ:để đạt được năm điểm cao nhất trong một bài kiểm tra, người dùng có thể ORDER BY
một score
và sau đó là LIMIT
kết quả là 5.
Trong khi LIMIT
đếm từ đầu kết quả theo mặc định, OFFSET
tùy chọn từ khóa có thể được sử dụng để bù đắp vị trí bắt đầu mà nó sử dụng. Trên thực tế, điều này cho phép bạn phân trang thông qua các kết quả bằng cách hiển thị số lượng kết quả được xác định bởi LIMIT
và sau đó thêm LIMIT
số cho OFFSET
để truy xuất trang sau.
Ví dụ sử dụng LIMIT
Chúng tôi sẽ sử dụng pet
bảng từ trước cho các ví dụ trong phần này.
Như đã đề cập ở trên, LIMIT
thường được kết hợp với ORDER BY
mệnh đề để xác định rõ ràng thứ tự của các hàng trước khi cắt số thích hợp. Ở đây, chúng tôi sắp xếp pet
mục nhập theo age
của chúng , từ lớn tuổi nhất đến trẻ tuổi nhất. Sau đó, chúng tôi sử dụng LIMIT
để hiển thị 5 động vật cổ nhất hàng đầu:
loạiSELECT * FROM pet ORDER BY age DESC LIMIT 5;
type | name | color | age | id--------+---------+--------+-----+---- cat | Simon | orange | 8 | 6 cat | Sabrina | black | 8 | 4 rabbit | Bunny | brown | 8 | 8 dog | Rover | black | 7 | 2 rabbit | Briany | brown | 6 | 9(5 rows)
Không có ORDER BY
mệnh đề, LIMIT
sẽ thực hiện các lựa chọn theo cách hoàn toàn có thể dự đoán được. Kết quả trả về có thể được thực hiện theo thứ tự của các mục trong bảng hoặc bởi các chỉ mục. Đây không phải lúc nào cũng là một điều xấu.
Nếu chúng tôi cần một bản ghi cho bất kỳ dog
nào trong bảng, chúng ta có thể tạo một truy vấn như thế này. Hãy nhớ rằng mặc dù kết quả có thể khó dự đoán, nhưng đây không phải là lựa chọn ngẫu nhiên và không nên được sử dụng như vậy:
loạiSELECT * FROM pet WHERE type = 'dog' LIMIT 1;
type | name | color | age | id------+------+-------+-----+---- dog | Spot | brown | 3 | 1(1 row)
Chúng ta có thể sử dụng OFFSET
mệnh đề phân trang thông qua kết quả. Chúng tôi bao gồm một ORDER BY
mệnh đề để xác định một thứ tự cụ thể cho các kết quả.
Đối với truy vấn đầu tiên, chúng tôi giới hạn kết quả mà không chỉ định OFFSET
để nhận được 3 bài dự thi trẻ nhất đầu tiên:
loạiSELECT * FROM pet ORDER BY age LIMIT 3;
type | name | color | age | id------+-------+-------+-----+---- dog | Sally | brown | 1 | 3 dog | Spot | brown | 3 | 1 cat | Felix | white | 4 | 5(3 rows)
Để có 3 người trẻ nhất tiếp theo, chúng ta có thể thêm số được xác định trong LIMIT
vào OFFSET
để bỏ qua kết quả mà chúng tôi đã truy xuất:
loạiSELECT * FROM pet ORDER BY age LIMIT 3 OFFSET 3;
type | name | color | age | id --------+---------+-------+-----+---- rabbit | Buttons | grey | 4 | 7 rabbit | Briany | brown | 6 | 9 dog | Rover | black | 7 | 2(3 rows)
Nếu chúng ta thêm LIMIT
vào OFFSET
một lần nữa, chúng ta sẽ nhận được 3 kết quả tiếp theo:
loạiSELECT * FROM pet ORDER BY age LIMIT 3 OFFSET 6;
type | name | color | age | id--------+---------+--------+-----+---- cat | Simon | orange | 8 | 6 rabbit | Bunny | brown | 8 | 8 cat | Sabrina | black | 8 | 4(3 rows)
Điều này cho phép chúng tôi truy xuất các hàng dữ liệu từ một truy vấn theo các phần có thể quản lý được.
Kết luận
Có nhiều cách để lọc và hạn chế kết quả bạn nhận được từ các truy vấn. Các mệnh đề như WHERE
và HAVING
đánh giá các hàng hoặc nhóm hàng tiềm năng để xem liệu chúng có thỏa mãn các tiêu chí nhất định hay không. GROUP BY
mệnh đề giúp bạn tóm tắt dữ liệu bằng cách nhóm các bản ghi có chung một hoặc nhiều giá trị cột với nhau. LIMIT
mệnh đề cung cấp cho người dùng khả năng đặt mức tối đa cố định về số lượng bản ghi cần truy xuất.
Học cách áp dụng các mệnh đề này, riêng lẻ hoặc kết hợp, sẽ cho phép bạn trích xuất dữ liệu cụ thể từ các tập dữ liệu lớn. Công cụ sửa đổi và bộ lọc truy vấn rất cần thiết để biến dữ liệu tồn tại trong PostgreSQL thành các câu trả lời hữu ích.