Запрос возвращает 418 записей, и вначале все результаты кажутся корректными. Поле ArtistId из таблицы artists соответствует полю ArtistId из таблицы albums. Большинство имен исполнителей связаны с названиями альбомов. Однако далее (рис. 81) мы обнаруживаем значения null.
Чтобы решить поставленную нам задачу и получить список исполнителей, у которых нет альбома, необходимо добавить условие WHERE, в котором следует указать только записи со значением NULL в таблице albums. Существуют определенные ключевые слова SQL, которые мы используем для работы со значениями NULL.
• ISNULL в условии WHERE вернет только нулевые значения.
• NOTNULL вернет только значения, которые не были нулевыми.
Рис. 81
Раздел WHEREal.ArtistIdISNULL вернет список исполнителей без названий альбомов.
Внимание
При работе со значениями NULL необходимо использовать операторы IS и NOT, а не оператор равенства =. Нулевые значения указывают на недостаток данных. Оператор = сравнивает значения двух элементов. Нулевые значения не содержат значений, поэтому их нельзя сравнивать, используя оператор =. Использование оператора = приведет к ошибке.
SELECT
ar.ArtistId AS [ArtistId From Artists Table],
al.ArtistId AS [ArtistId From Albums Table],
ar.Name AS [Artist Name],
al.Title AS [Album]
FROM
artists AS ar
LEFT OUTER JOIN
albums AS al
ON
ar.ArtistId = al.ArtistId
WHERE
al.ArtistId IS NULL
Полученные результаты (рис. 82) содержат 71 запись, в которой нет альбомов и имен исполнителей.
Рис. 82
Преобразование правого соединения в левое
Как мы уже говорили, правые соединения в SQLite не поддерживаются. Мы также узнали, что правые соединения — это зеркальное отображение левых соединений. Рассмотрим диаграмму Венна.
При использовании правого соединения берутся все записи с правой стороны и объединяются со всеми соответствующими записями с левой стороны. Если вы просто поменяете местами левую и правую таблицы, то для получения того же результата вы можете использовать левое внешнее соединение. Следующий запрос написан с использованием правого внешнего соединения. В данном запросе любая соответствующая информация об альбоме или названии из таблицы albums объединяется со всеми записями из таблицы tracks.
SELECT * FROM albums AS al RIGHT OUTER JOIN tracks AS t ON t.AlbumId = al.AlbumId
аналогично
SELECT * FROM tracks AS t LEFT OUTER JOIN albums AS al ON t.AlbumId = al.AlbumId
Рис. 83
SELECT
t. TrackId,
t. Composer,
t. Name,
al.AlbumId,
al.Title
FROM
albums AS al
RIGHT OUTER JOIN
tracks AS t
ON
t. AlbumId = al.AlbumId
При выполнении предыдущего запроса возникнет следующая ошибка: RIGHTandFULLOUTERJOINsarenotcurrentlysupported (Правое и полное внешние соединения в настоящее время не поддерживаются).
Однако для решения данной проблемы мы можем просто поменять местами таблицы. Рассмотрим следующий запрос, единственное отличие которого от предыдущего — порядок перечисления таблиц.
SELECT
t. TrackId,
t. Composer,
t. Name,
al.AlbumId,
al.Title
FROM
tracks AS t
LEFT OUTER JOIN
albums AS al
ON
t. AlbumId = al.AlbumId
Выполним его и проанализируем полученные результаты (рис. 84). Мы получим следующую информацию в одном наборе результатов: композитор, название песни и название альбома. Обратите внимание, что в поле Composer (Композитор) обнаружилось несколько нулевых значений. Теперь можно написать другой запрос, чтобы разобраться, в чем дело.
Главный вывод от использования левых/правых соединений: они могут «устранить неполадки» в нашей базе данных и выявить несоответствия в данных.
Если вам нужно найти соответствующие данные и вам не критично потерять несколько записей из-за ошибок в базе данных, то просто пользуйтесь соединением INNER JOINT.
Рис. 84
Практическое задание
• Измените приведенный выше запрос так, чтобы отображались только записи, в которых поле Composer содержит значение NULL.
Контрольные вопросы
1. Используя DB Browser и вкладку Browse Data (Просмотр данных) или ER-диаграмму (рис. 65), проанализируйте таблицу tracks. Определите, какие поля в этой таблице будут внешними ключами в другой таблице. На основании определенных вами внешних ключей определите, какие таблицы связаны с таблицей tracks.
2. Создайте внутреннее соединение между таблицами albums и tracks и отобразите названия альбомов и названия треков в едином наборе результатов.
3. Создайте третье внутреннее соединение — с таблицей genres, которую вы нашли, отвечая на вопрос 1. Включите в ваш набор результатов поле Name из этой таблицы.
Резюме
• Соединения используются для соединения данных из разных таблиц.
• При написании соединений полезно использовать ER-диаграмму.
• При одновременном выборе полей из нескольких таблиц для указания исходной таблицы необходимо использовать псевдонимы.
• Внутренние соединения не включают строки, для которых нет соответствующих данных.
• Внешние соединения включают все строки одной из таблиц, даже если между таблицами нет соответствующих данных. Несовпадающие строки будут отображаться как Null.