- •Глава 3. Учебное пособие по MySql
- •3.1. Подсоединение к серверу и отсоединение от него
- •3.2. Ввод запросов
- •3.3. Создание и использование базы данных
- •3.3.1. Создание и выбор базы данных
- •3.3.2. Создание таблицы
- •3.3.3. Загрузка данных в таблицу
- •3.3.4. Выборка информации из таблицы
- •3.3.4.1. Выборка всех данных
- •3.3.4.2. Выборка определенных строк
- •3.3.4.3. Выборка определенных столбцов
- •3.3.4.4. Сортировка строк
- •3.3.4.5. Вычисление дат
- •3.3.4.6. Работа с значениями null
- •3.3.4.7. Сравнение по шаблонам
- •3.3.4.8. Подсчет строк
- •3.3.4.9. Использование нескольких таблиц
- •3.4. Получение информации о базах данных и таблицах
- •3.5. Примеры стандартных запросов
- •3.5.1. Максимальное значение столбца
- •3.5.2. Строка, содержащая максимальное значение некоторого столбца
- •3.5.3. Максимальное значение столбца для группы
- •3.5.4. Строка, содержащая максимальное значение некоторого столбца
- •3.5.5. Использование пользовательских переменных
- •3.5.6. Использование внешних ключей
- •3.5.7. Поиск по двум ключам
- •3.5.8. Подсчет посещений за день
- •3.5.9. Использование атрибута auto_increment
- •3.6. Использование mysql в пакетном режиме
- •3.7. Запросы проекта 'Близнецы' (Twin Project)
- •3.7.1. Поиск нераспределенных близнецов
- •3.7.2. Вывод таблицы состояний пар близнецов
- •3.8. Использование MySql совместно с Apache
3.5.1. Максимальное значение столбца
"Как определить наибольшее значение в столбце?"
SELECT MAX(article) AS article FROM shop
+---------+
| article |
+---------+
| 4 |
+---------+
3.5.2. Строка, содержащая максимальное значение некоторого столбца
"Как определить номер, дилера и цену самого дорогого изделия?"
В ANSI SQL (и MySQL 4.1) это легко делается при помощи вложенного запроса:
SELECT article, dealer, price
FROM shop
WHERE price=(SELECT MAX(price) FROM shop)
В версиях MySQL до 4.1 такая задача выполняется в два этапа:
Следует получить максимальное значение цены из таблицы при помощи оператора SELECT.
Используя это значение, необходимо составить следующий запрос:
SELECT article, dealer, price
FROM shop
WHERE price=19.95
Существует еще одно решение: отсортировать все строки по убыванию цен и после этого получить первую строку, используя специальный оператор LIMIT:
SELECT article, dealer, price
FROM shop
ORDER BY price DESC
LIMIT 1
Примечание: если существует несколько самых дорогих изделий (например, каждое из них стоит 19,95), запрос, использующий LIMIT, возвращает лишь одно из них!
3.5.3. Максимальное значение столбца для группы
"Как определить наибольшую цену по каждому изделию?"
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 |
+---------+-------+
3.5.4. Строка, содержащая максимальное значение некоторого столбца
"Для каждого изделия, как определить дилер(ов) с самыми высокими ценами?"
В ANSI SQL (и MySQL 4.1) это легко делается при помощи вложенного запроса:
SELECT article, dealer, price
FROM shop s1
WHERE price=(SELECT MAX(s2.price)
FROM shop s2
WHERE s1.article = s2.article);
В MySQL до 4.1 такая задача выполняется в два этапа:
Следует получить список (изделие, максимальная цена)
Для каждого изделия, получить соответствующие записи, в которых цена соответствует максимальной.
Это легко делается с помощью временной таблицы:
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.
"А можно ли это сделать одним запросом?"
Да, но только используя совершенно неэффективный трюк, который я называю "Трюк MAX-CONCAT":
SELECT article,
SUBSTRING( MAX( CONCAT(LPAD(price,6,'0'),dealer) ), 7) AS dealer,
0.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 |
+---------+--------+-------+
Разумеется, последний пример можно сделать чуть эффективнее, если разбиение катенизированной строки делать на стороне клиента.
