Выборка из базы данных - это основная часть нашей работы. Без запросов в базу данных нельзя сделать полноценный динамический сайт. Запрос к одной таблице - это простая задача, а вот запрос к нескольким таблицам - сложная задача. Тут легко запутаться. Очень важно научиться вытаскивать массив значений из базы данных Firebird по определённому запросу.
#Поиск записей о продажах, для которых не установлена дата отгрузки:
SELECT *
FROM SALES
WHERE SHIP_DATE IS NULL;
Как это не странно, но NULL - тоже значение. Вы можете использовать поиск по нему. При записи в базу данных важно учитывать какое поле может быть пустым, а какое должно быть с определённым значением.
#Найти тех сотрудников, у которых нет проектов
SELECT *
FROM employee
WHERE NOT EXISTS(SELECT *
FROM
employee_project ep
WHERE
ep.emp_no = employee.emp_no)
Очень удобно использовать подзапрос IN. Вы могли бы через запятую перечислить значения, но это приведёт к тому, что запрос будет статичным и вам каждый раз придётся его менять. К тому же число значений в подзапросе может быть достаточно большим. В этом случае длина SQL-запроса может быть довольно большой. Если вам нужно передать массив PHP в подзапрос IN, то перейдите на страницу Как превратить массив в строку для оператора IN() PHP. Массив будет превращён в строку. Например, строка с id: '1,2,3,4,5,6,7'
#IN(подзапрос)
SELECT *
FROM SHOP
WHERE SHOP_ID IN(SELECT SHOP_ID
FROM SHOP
WHERE SHOP_ID >1 AND SHOP_ID < 6);
#NOT IN(подзапрос) если не соответствует
SELECT *
FROM SHOP
WHERE SHOP_ID NOT IN(SELECT SHOP_ID
FROM SHOP
WHERE SHOP_ID >1 AND SHOP_ID < 6);
#выборка по нескольким значениям одного поля
SELECT *
FROM SHOP
WHERE SHOP_ID NOT IN(1,2,3);
Подзапросы хороши тем, что вам не нужно делать несколько запросов, а потом работать с массивами. Вы облегчите себе труд. Будет минимум писанины.
#EXISTS(подзапрос)
SELECT *
FROM SHOP
WHERE EXISTS(SELECT SHOP_ID
FROM SHOP
WHERE SHOP_ID >1 AND SHOP_ID < 6);
#ALL Вывести только тех заказчиков, чьи оценки выше,
#чем у каждого заказчика в Париже
SELECT *
FROM Customers
WHERE rating > ALL
(SELECT rating
FROM Customers
WHERE city = 'Paris')
В Firebird нет Limit как в MySQL. Тут нужно использовать FIRST.
#FIRST первые 2
SELECT FIRST 2 SHOP_ID
FROM SHOP
#SKIP - последующие
SELECT SKIP 2 SHOP_ID
FROM SHOP
При удалении записи в базе дынных будьте особенно осторожными. Многие программисты лишились работы из-за удаления базы. Данные базы чаще всего представляют коммерческую ценность и вы не имеете право полностью удалять данные таблицы. При удалении записей обязательно должно быть условие и желательно не одно, иначе вы очистите всю таблицу.
#FIRST (SELECT только в скобках)
DELETE FROM MYTABLE
WHERE ID IN (SELECT FIRST 10 ID FROM MYTABLE)
#последние 2 записи
SELECT skip ((select count(*) - 2 from SHOP)) SHOP_NAME, SHOP_ID
FROM SHOP
#Этот запрос вернет строки 81-100 из таблицы PEOPLE:
select first 20 skip 80 id, name
from People
order by name asc
Очень часто нужно увидеть на экране уникальные значения. Тут без DISTINCT не обойтись. DISTINCT является неким фильтром, который удаляет повторяющиеся значения.
#без повторов
SELECT DISTINCT SHOP_NAME
FROM SHOP
#группировка
SELECT SHOP_NAME
FROM SHOP GROUP BY SHOP_NAME
#магазин + группировка + Большие буквы
SELECT 'магазин ' || upper(SHOP_NAME)
FROM SHOP GROUP BY SHOP_NAME
Удобно использовать маленькое начертание букв при помощи lower. Вы можете использовать php-функцию mb_strtolower(). Её часто придется применять, что не очень удобно.
#условие + приведение к маленькому регистру
select
case lower(SHOP_NAME)
when 'майкоп' then 'Майкоп::2015'
when 'ростов' then 'Ростов::2015'
else '-нет-'
end as title,
SHOP_ID
from SHOP
# left join
select *
from A
left [outer] join B on A.id = B.code
Вязание таблиц между собой - это самый сложный этап работы. Я часто ломаю голову и редко пишу сложный SQL-запрос без ошибок. Тут вам придется собраться и набраться терпения. Ошибка в один символ приведёт к ошибке в запросе. Вы должны будите привязать таблицы по параметрам. Чаще всего вяжут таблицы по ID.
#выборка
select *
from flotsam f
join jetsam j
on f.sea = j.sea
and f.ship = j.ship
#или
select *
from flotsam
join jetsam using (sea, ship)
# Перестроим наши ранние примеры. Мы можем использовать предложение
# HAVING для исключения малых групп студентов:
select
class,
count(*) as num_boys,
avg(age) as boys_avg_age
from students
where sex = 'M'
group by class
having count(*) >= 5
#Выберем только группы, которые имеют минимальный разброс по возрасту
#1,2 года
select
class,
count(*) as num_boys,
avg(age) as boys_avg_age
from students
where sex = 'M'
group by class
having max(age) - min(age) > 1.2
Часто приходится выводить на странице наиболее характерные значения. Например самый большой заказ в рублях. Если вы будите использовать php, вы должны использовать специальную встроенную функцию. Это лишняя нагрузка на сервер.
#максимальные и минимальные значения
SELECT mix(SHOP_ID) FROM SHOP
SELECT max(SHOP_ID) FROM SHOP
#среднее значение
SELECT avg(SHOP_ID) FROM SHOP
Иногда нужно объединять несколько таблиц. Помните, что количество полей должно совпадать как по количеству, так и по типу. Если не получается объединить выборку из 2 таблиц, то применить union all.
#Этот запрос представляет информацию из различных музыкальных
#коллекций в одном наборе данных с помощью объединений:
select id, title, artist, length, 'CD' as medium
from cds
union
select id, title, artist, length, 'LP'
from records
union
select id, title, artist, length, 'MC'
from cassettes
order by 3, 2 -- artist, title