Самоучитель по SQL-сервер в Linux



Удаление дубликатов и ключевое слово DISTINCT

Необязательное ключевое слово DISTINCT исключает дубликаты из итогового набора. Если ключевое слово ON отсутствует, из результатов запроса с ключевым словом DISTINCT исключаются записи с повторяющимися значениями целевых полей. Проверяются только поля, входящие в целевой список SELECT.

Предположим, таблица books содержит 15 записей, в каждой из которых присутствует поле authorjd. Некоторые коды авторов многократно встречаются в таблице books. Включение в запрос ключевого слова DISTINCT (листинг 4.31) гарантирует, что итоговый набор будет содержать не более одной записи для каждого автора.

Листинг 4.31. Ключевое слово DISTINCT

booktown=# SELECT DISTINCT author_id

booktown-# FROM books;

author_id

16

115

1212

1644

1809

1866

2001

2031

4156

7805

7806

15990

25041

(13 rows)

booktown=# SELECT DISTINCT ON (author_id)

booktown-# author_id. title

booktown-# FROM books;

author_id | ntitle

16 | Little Women

115 | The Tell-Tale Heart

1212 | Practical PostgreSQL

1644 | Dynamic Anatomy

1809 | The Cat in the Hat

1866 | Dune

2001 | 2001: A Space Odyssey

2031 | Goodnight Moon

4156 | The Shining

7805 | Programming Python

7806 | Perl Cookbook

15990 |Franklin in the Dark

25041 | The Velveteen Rabbit

(13 rows)

Первый запрос в листинге 4.31 возвращает только 13 записей из таблицы books, хотя таблица содержит 15 записей. Два автора, написавшие по две книги, вошли в итоговый набор лишь в одном экземпляре.

Во втором запросе использована другая форма DISTINCT с явным перечислением полей (или выражений), проверяемых на наличие дубликатов. В этом случае запрос также возвращает 13 записей, поскольку секция ON указывает, что дубликаты проверяются по значению поля author_i d. Без секции ON запрос верн)и бы все 15 записей, поскольку по умолчанию PostgreSQL проверяет полное совпадение всех полей.

В общем случае PostgreSQL выбирает записи, исключаемые из итогового набора при наличии секции ON, по своему усмотрению. Если в запрос вместе с DISTINCT входит секция ORDER BY, вы можете самостоятельно задать порядок выборки полей так, чтобы нужные записи оказались в начале. Сортировка записей рассматривается в подразделе «Сортировка записей».

Если вместо исключения всех дубликатов достаточно сгруппировать записи с повторяющимися значениями некоторого критерия, воспользуйтесь секцией GROUP BY, описанной в подразделе «Группировка записей».

Уточнение запросов

В секции WHERE задается логическое условие, которому должны удовлетворять записи итогового набора. На практике команда SELECT почти всегда содержит как минимум одну уточняющую секцию WHERE.

Предположим, вы хотите получить список всех книг о компьютерных технологиях в базе данных booktown. У этих книг поле subject_id равно 4. Соответственно в секцию WHERE включается оператор =, который проверяет это условие. Пример приведен в листинге 4.32.

Листинг 4.32. Простая секция WHERE

booktown=# SELECT * FROM books

booktown-# WHERE subject_id = 4;

id | title | author_id | subject_id

41472 | Practical PostgreSQL | 1212 | 4

41473 | Programming Python | 7805 | 4

41477 | Learning PostgreSQ L | 7805 | 4

41478 | Perl Cookbook | 7806 | 4

(4 rows)

Запрос из листинга 4.32 возвращает только те записи, у которых поле subject_id совпадает с целочисленной константой 4. Итоговый набор содержит всего 4 записи книг о компьютерах вместо 15 записей, приведенных в листинге 4.23.

Секция WHERE может содержать несколько условий, объединенных логическими операторами (например, AND или OR) и возвращающими одно логическое значение. Допустим, вас интересуют все записи для книг о компьютерах, которые, кроме того, что они о компьютерах, написаны Марком Лутцем. Запрос уточняется объединением двух условий при помощи логического оператора AND. Возможен и другой вариант — например, поиск всех книг, посвященных компьютерным технологиям или искусству; в этом случае два условия объединяются логическим оператором OR. В листинге 4.33 продемонстрированы оба сценария с ключевыми словами AND и OR.

Листинг 4.33. Объединение условий в секции WHERE

booktown=# SELECT title FROM books

booktown-# WHERE subject_id = 4

booktown-# AND author_id = 7805;

title

Programming Python

Learning Python

(2 rows)

booktown=# SELECT title FROM books

booktown-# WHERE subject_id = 4

booktown-# AND author_id = 0;

title

Dynamic Anatomy

Practical PostgreSQL

Programming Python

Learning Python

Perl Cookbook

(5 rows)

Первая команда SELECT в листинге 4.33 содержит два условия, объединенных логическим оператором AND. Первое условие проверяет, что книга посвящена компьютерным технологиям (поле subject_id равно 4), а второе — что автором книги является Марк Лутц (поле author_id равно 7805). Объединение условий уменьшает объем итогового набора — в него входят всего две записи, удовлетворяющие обоим условиям.

Во второй команде SELECT в листинге 4.33 прежнее первое условие (книги по компьютерной тематике) объединяется со вторым условием: книги по искусству (поле subject_id равно 0). В результате объем итогового набора увеличивается до пяти записей, каждая из которых удовлетворяет хотя бы одному из этих условий.

Количество условий, объединяемых в секции WHERE, не ограничено, хотя при наличии двух и более условий обычно выполняется группировка при помощи круглых скобок, наглядно демонстрирующая логическую связь между условиями. Листинг 4.34 показывает, как простое добавление круглых скобок влияет на результат выполнения команды.

Листинг 4.34. Группировка условий при помощи круглых скобок

booktown=# SELECT * FROM books

booktown-# WHERE author_id = 1866

booktown-# AND subject_id = 15

booktown-# OR subject_id = 3;

id | title | autho_id | subject_id

4513 | Dune | 1866 | 15

1234 | The Velveteen Rabbit | 25041 | 3

(2 rows)

booktown=# SELECT * FROM books

booktown-# WHERE author_id = 1866

booktown-# AND (subject_id = 15

booktown-# OR subject_id = 3);

id | title | author_id | subject_id

4513 | Dune | 1866 | 15

(1 row)

В этом примере продемонстрированы две попытки выборки из базы данных booktown записей, у которых поле author_id равно 1866. Кроме того, поле subject_id должно быть равно либо 15, либо 3. Как видно из результатов первой команды, при перечислении всех трех условий без круглых скобок команда интерпретируется неправильно. Добавление круглых скобок приводит к тому, что вычисления в скобках производятся до проверки внешних условий.