- •Типы данных столбцов
- •Пример:
- •То автоматически генерируется уникальный id (то же, если поле id вообще не указывать в команде вставки).
- •Обычно, следует выполнять select для set-столбца, используя оператор like или функцию find_in_set():
- •Но и такая форма также работает:
- •'Yyyy-mm-dd',yy-mm-dd' Например '98-12-31', "98.12.31', '98/12/31'
- •Describe messy # Описать таблицу 'messy'
- •Например, drop table people, animals, plants удалит эти три таблицы. Drop table oh_no, help_me, dont_do_it # Удалить таблицы 'oh_no', 'help_me' и 'dont_do_it'
- •Например, можно указать следующее:
- •Но нельзя указать:
- •Например:
- •Быстрая загрузка данных
- •Синтаксис оператора truncate
- •Примеры:
- •(Например, select name from people; select mydata.People.Name from people ).
- •Подзапросы -- Язык sql разрешает использовать в других операторах языка dml подзапросы, которые являются внутренними запросами, определяемыми оператором select.
- •Применение подзапросов в операторах изменения данных
- •Демонстрируется использование mysql в качестве несложного калькулятора:
- •Проверка таблицы при помощи команды describe:
- •Выборка всех данных
- •Выборка определенных строк. Выборка с условием Из таблицы можно выбрать и только нужные строки, если надо проверить правильность внесенных в дату рождения собаки Bowser изменений:
- •В условиях может указываться любой из столбцов:
- •Условия можно и комбинировать, например для того, чтобы выделить всех собак женского пола:
- •В предыдущем запросе использован оператор and. Существует еще и оператор or:
- •Операторы and и or можно использовать совместно.
- •Выборка определенных столбцов Достаточно просто перечислить имена нужных столбцов, разделив их запятыми.
- •Получить имена владельцев животных можно с помощью следующего запроса:
- •Сократить количество выводимых строк можно, воспользовавшись ключевым словом distinct - тогда будут выводиться только уникальные записи:
- •При помощи выражения where можно комбинировать выбор строк и столбцов. Например для того, чтобы загрузить даты рождения только кошек и собак, можно воспользоваться следующим запросом:
- •Сортировка строк Для этого используется выражение order by.
- •Предположим, нужно узнать, в каком возрасте животные давали приплод:
- •В этом запросе мы указываем псевдонимы имен таблицы, для обращения к столбцам и определения, к какой из таблиц относится каждая ссылка на столбец.
- •Сортировку можно проводить по нескольким столбцам сразу.
- •Отсортировать результаты по возрасту также можно при помощи выражения order by:
- •Этот запрос подсчитывает, сколько различных дней входит в данную комбинацию год/месяц, автоматически исключая дублирующиеся значения.
Отсортировать результаты по возрасту также можно при помощи выражения order by:
mysql> SELECT name, birth, CURRENT_DATE, (YEAR(CURRENT_DATE)-YEAR(birth))
-> - (RIGHT(CURRENT_DATE,5)<RIGHT(birth,5)) AS age FROM pet ORDER BY age;
name |
birth |
CURRENT_DATE |
age |
Chirpy |
1998-09-11 |
2001-08-29 |
2 |
Puffball |
1999-03-30 |
2001-08-29 |
2 |
Whistler |
1997-12-09 |
2001-08-29 |
3 |
Slim |
1996-04-29 |
2001-08-29 |
5 |
Claws |
1994-03-17 |
2001-08-29 |
7 |
Fluffy |
1993-02-04 |
2001-08-29 |
8 |
Fang |
1990-08-27 |
2001-08-29 |
11 |
Bowser |
1989-08-31 |
2001-08-29 |
11 |
Buffy |
1989-05-13 |
2001-08-29 |
12 |
Подобный же запрос поможет определить возраст, которого достигли умершие животные на момент смерти. Выделить умерших животных можно, проверив значение поля death на предмет равенства NULL. Затем для записей, значения поля death которых не равно NULL, можно вычислить разницу между датами смерти и рождения:
mysql> SELECT name, birth, death, (YEAR(death)-YEAR(birth)) - (RIGHT(death,5)<RIGHT(birth,5)) AS age FROM pet WHERE death IS NOT NULL ORDER BY age;
name |
birth |
death |
age |
Bowser |
1989-08-31 |
1995-07-29 |
5 |
В MySQL предусмотрено несколько функций для получения частей дат - YEAR(), MONTH(), и DAYOFMONTH(). mysql> SELECT name, birth, MONTH(birth) FROM pet;
name |
birth |
MONTH(birth) |
Fluffy |
1993-02-04 |
2 |
Claws |
1994-03-17 |
3 |
Buffy |
1989-05-13 |
5 |
Fang |
1990-08-27 |
8 |
Bowser |
1989-08-31 |
8 |
Chirpy |
1998-09-11 |
9 |
Whistler |
1997-12-09 |
12 |
Slim |
1996-04-29 |
4 |
Puffball |
1999-03-30 |
3 |
Найти животных, дни рождения которых наступят в следующем месяце, тоже несложно. Предположим, что сейчас на дворе апрель. Тогда номер текущего месяца - 4, а искать надо животных, родившихся в мае (5-м месяце), таким образом:
mysql> SELECT name, birth FROM pet WHERE MONTH(birth) = 5;
name |
birth |
Buffy |
1989-05-13 |
Конечно, в декабре возникают некоторые осложнения. Если просто добавить единицу к номеру месяца (12) и поискать животных, родившихся в тринадцатом месяце, найти что-нибудь вряд ли удастся. Вместо этого нужно искать животных, родившихся в январе (1-м месяце). Можно даже написать небольшой запрос, который будет работать вне зависимости от того, какой нынче месяц. Функция DATE_ADD() позволяет прибавить к дате некоторый интервал времени. Если добавить к значению, возвращаемому функцией NOW(), месяц, а затем извлечь из получившейся даты номер месяца при помощи функции MONTH(), мы получим именно тот месяц, который нам нужен:
mysql> SELECT name, birth FROM pet WHERE MONTH(birth) = MONTH(DATE_ADD(NOW(), INTERVAL 1 MONTH));
Ту же задачу можно решить и другим методом - для этого нужно прибавить единицу к номеру месяца, следующего за текущим (воспользовавшись функцией расчета по модулю (MOD) для перехода к 0, если номер текущего месяца равен 12):
mysql> SELECT name, birth FROM pet WHERE MONTH(birth) = MOD(MONTH(NOW()), 12) + 1;
Функция MONTH возвращает число от 1 до 12, а выражение MOD(число,12) - число от 0 до 11. Поэтому операцию сложения нужно проводить после MOD(), иначе результат перепрыгнет с ноября (11) сразу на январь (1).
Примеры стандартных запросов
В некоторых из примеров используется таблица shop (магазин), в которой содержатся цены по каждому изделию (item number)для определенных продавцов (dealer). Каждый продавец имеет одну фиксированную цену для каждого изделия; тогда пара изделие-продавец (article, dealer) является первичным ключом для записей таблицы.
CREATE TABLE shop ( article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL, dealer CHAR(20) DEFAULT '' NOT NULL, price DOUBLE(16,2) DEFAULT '0.00' NOT NULL, PRIMARY KEY(article, dealer));
INSERT INTO shop VALUES(1,'A',3.45),(1,'B',3.99),(2,'A',10.99),(3,'B',1.45),(3,'C',1.69),(3,'D',1.25),(4,'D',19.95);
mysql> SELECT * FROM shop;
article |
dealer |
price |
0001 |
A |
3.45 |
0001 |
B |
3.99 |
0002 |
A |
10.99 |
0003 |
B |
1.45 |
0003 |
C |
1.69 |
0003 |
D |
1.25 |
0004 |
D |
19.95 |
Максимальное значение столбца
SELECT MAX(article) AS article FROM shop
article |
4 |
"Как определить номер, дилера и цену самого дорогого изделия?"
SELECT article, dealer, price FROM shop WHERE price=(SELECT MAX(price) FROM shop)
Следует получить максимальное значение цены из таблицы при помощи оператора SELECT, используя это значение, необходимо составить следующий запрос:
SELECT article, dealer, price FROM shop WHERE price=19.95
Существует еще одно решение: отсортировать все строки по убыванию цен и после этого получить первую строку, используя специальный оператор LIMIT:
SELECT article, dealer, priceFROM shop ORDER BY price DESC LIMIT 1
Примечание: если существует несколько самых дорогих изделий (например, каждое из них стоит 19,95), запрос, использующий LIMIT, возвращает лишь одно из них!
Как определить наибольшую цену по каждому изделию?
SELECT article, MAX(price) AS price FROM shop GROUP BY article
article |
|price |
0001 |
3.99 |
0002 |
10.99 |
0003 |
1.69 |
0004 |
19.95 |
Для каждого изделия, как определить дилер(ов) с самыми высокими ценами?
SELECT article, dealer, price FROM shop s1 WHERE price=
(SELECT MAX(s2.price) FROM shop s2 WHERE s1.article = s2.article);
1.Следует получить список (изделие, максимальная цена)
2.Для каждого изделия, получить соответствующие записи, в которых цена соответствует максимальной.
Это легко делается с помощью временной таблицы:
CREATE TEMPORARY TABLE tmp ( article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL, price DOUBLE(16,2) DEFAULT '0.00' NOT NULL);
LOCK TABLES shop read;
INSERT INTO tmp SELECT article, MAX(price) FROM shop GROUP BY article;
SELECT shop.article, dealer, shop.price FROM shop, tmp
WHERE shop.article=tmp.article AND shop.price=tmp.price;
UNLOCK TABLES;
DROP TABLE tmp;
Если не использовать ключевое слово TEMPORARY, следует поставить блокировку на таблицу tmp.
"А можно ли это сделать одним запросом?"
SELECT article, SUBSTRING( MAX( CONCAT(LPAD(price,6,'0'),dealer) ), 7) AS dealer,00+LEFT( MAX( CONCAT(LPAD(price,6,'0'),dealer) ), 6) AS price FROM shop GROUP BY article;
article |
dealer |
price |
0001 |
B |
3.99 |
0002 |
A |
10.99 |
0003 |
C |
1.69 |
0004 |
D |
19.95 |
Использование пользовательских переменных
В MySQL для хранения результатов, чтобы не держать их во временных переменных на клиенте, можно применять пользовательские переменные
Например, для того чтобы найти изделия с максимальной или минимальной ценой, можно выполнить следующие действия:
mysql> SELECT @min_price:=MIN(price),@max_price:=MAX(price) FROM shop;
mysql> SELECT * FROM shop WHERE price=@min_price OR price=@max_price;
article |
dealer |
price |
0003 |
D |
1.25 |
0004 |
D |
19.95 |
Поиск по двум ключам
MySQL пока не осуществляет оптимизации, если поиск производится по двум различным ключам, которые связаны при помощи оператора OR (поиск по одному ключу с различными частями OR оптимизируется хорошо):
SELECT field1_index, field2_index FROM test_table WHERE field1_index = '1'OR field2_index = '1'
В настоящее время данную проблему очень эффективно можно решить при помощи временной таблицы. Этот способ оптимизации также хорошо подходит, если вы запускаете очень сложные запросы, когда SQL-сервер делает оптимизацию в неправильном порядке.
CREATE TEMPORARY TABLE tmp
SELECT field1_index, field2_index FROM test_table WHERE field1_index = '1';
INSERT INTO tmp
SELECT field1_index, field2_index FROM test_table WHERE field2_index = '1';
SELECT * from tmp;
DROP TABLE tmp;
Вышеупомянутый способ выполнения этого запроса - это фактически UNION (объединение) двух запросов.
Подсчет посещений за день
В этом разделе представлен пример использования групповых побитовых функций для вычисления дней месяца, когда пользователь заходил на веб-сайт.
CREATE TABLE t1 (year YEAR(4), month INT(2) UNSIGNED ZEROFILL,day INT(2) UNSIGNED ZEROFILL);
INSERT INTO t1 VALUES(2000,1,1),(2000,1,20),(2000,1,30),(2000,2,2),(2000,2,23),(2000,2,23);
SELECT year,month,BIT_COUNT(BIT_OR(1<<day)) AS days FROM t1 GROUP BY year,month;
year |
month |
days |
2000 |
01 |
3 |
2000 |
02 |
2 |