Использование в запросе нескольких источников записей

Использование в запросе нескольких источников записей

Как видно из приведенной в конце предыдущего раздела синтаксической формы оператора SELECT, в предложении FROM допускается указание нескольких таблиц. Простое перечисление таблиц через запятую практически не используется, поскольку оно соответствует реляционной операции, которая называется декартовым произведением. То есть в результирующем наборе каждая строка из одной таблицы будет сочетаться с каждой строкой из другой. Например, для таблиц:

Таблица A

ab
12
21

Таблица B

cd
24
33

Результат запроса

SELECT *
FROM A, B;

будет выглядеть следующим образом:

abcd
1224
1233
2124
2133

Поэтому перечисление таблиц, как правило, используется совместно с условием соединения строк из разных таблиц, указываемым в предложении WHERE. Для приведенных выше таблиц таким условием может быть совпадение значений, скажем, в столбцах a и c:

SELECT *
FROM A, B
WHERE a = c;

Теперь результатом выполнения этого запроса будет следующая таблица:

abcd
2124

то есть соединяются только те строки таблиц, у которых в указанных столбцах находятся равные значения (эквисоединение). Естественно, могут быть использованы любые условия соединения, хотя эквисоединение используется чаще всего, поскольку эта операция воссоздает некую исходную сущность предметной области, декомпозированную на две других в результате процедуры нормализации в процессе построения логической модели.

Если разные таблицы имеют столбцы с одинаковыми именами, то для однозначности требуется использовать точечную нотацию, которая называется уточнением имени столбца:

<имя таблицы>.<имя столбца>

В тех случаях, когда это не вызывает неоднозначности, использование данной нотации не является обязательным.

Пример 5.6.1

Найти номер модели и производителя ПК, имеющих цену менее $600:
SELECT DISTINCT PC.model, maker
FROM PC, Product
WHERE PC.model = Product.model 
    AND price < 600;
mssql
🚫
[[ error ]]
[[ column ]]
[[ value ]]

В результате каждая модель одного и того же производителя выводится только один раз (DISTINCT):

modelmaker
1232A
1260E

Иногда в предложении FROM требуется указать одну и ту же таблицу несколько раз. В этом случае обязательным является переименование.

Пример 5.6.2

Вывести пары моделей, имеющих одинаковые цены:
SELECT DISTINCT A.model AS model_1, B.model AS model_2
FROM PC AS A, PC B
WHERE A.price = B.price 
    AND A.model < B.model;
mssql
🚫
[[ error ]]
[[ column ]]
[[ value ]]

Здесь условие a.model < b.model используется для того, чтобы не выводились одинаковые пары, отличающиеся только перестановкой, например: {1232, 1233} и {1233, 1232}. DISTINCT применяется для того, чтобы исключить одинаковые строки, поскольку в таблице PC имеются модели с одинаковыми номерами по одной и той же цене. В результате получим следующую таблицу:

model_1model_2
12321233
12321260

Переименование также является обязательным, если в предложении FROM используется подзапрос, так как, в противном случае, у нас нет возможности уточнения имени столбца из подзапроса. Так, первый пример можно переписать следующим образом:

SELECT DISTINCT PC.model, maker
FROM PC, (SELECT maker, model
          FROM Product
         ) AS Prod
WHERE PC.model = Prod.model 
    AND price < 600;
mssql
🚫
[[ error ]]
[[ column ]]
[[ value ]]

Обратите внимание, что в этом случае в других предложениях оператора SELECT уже нельзя использовать квалификатор Product, поскольку таблица Product уже не используется. Вместо него используется псевдоним Prod. Кроме того, ссылаться извне теперь можно только на те столбцы таблицы Product, которые перечислены в подзапросе.

За псевдонимом производного табличного выражения может в скобках стоять список имен столбцов, которые будут использоваться вместо имен столбцов табличного выражения. Порядок имен должен, естественно, соответствовать списку столбцов табличного выражения (в нашем случае - списку в предложении SELECT). Это способ позволяет избежать неоднозначности имен и, как следствие, необходимости их уточнения. Вот как может выглядеть предыдущий пример:

SELECT DISTINCT model, maker
FROM PC, (SELECT maker, model
          FROM Product
         ) AS Prod(maker, model_1)
WHERE model = model_1 
    AND price < 600;
mssql
🚫
[[ error ]]
[[ column ]]
[[ value ]]

Рекомендуемые упражнения: 16, 17, 34, 96, 108