SELECT
HANDLER
INSERT
INSERT DELAYED
UPDATE
DELETE
TRUNCATE
REPLACE
LOAD DATA INFILE
DO
SELECT
Оператор SELECT имеет следующую структуру:
SELECT [STRAIGHT_JOIN] [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT] [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS] [HIGH_PRIORITY] [DISTINCT | DISTINCTROW | ALL] select_expression,... [INTO {OUTFILE | DUMPFILE} 'file_name' export_options] [FROM table_references [WHERE where_definition] [GROUP BY {unsigned_integer | col_name | formula} [ASC | DESC], ...] [HAVING where_definition] [ORDER BY {unsigned_integer | col_name | formula} [ASC | DESC], ...] [LIMIT [offset,] rows | rows OFFSET offset] [PROCEDURE procedure_name(argument_list)] [FOR UPDATE | LOCK IN SHARE MODE]]
SELECT
применяется для извлечения строк, выбранных из одной или нескольких
таблиц. Выражение select_expression
задает столбцы, в которых необходимо
проводить выборку. Кроме того, оператор SELECT
можно использовать для
извлечения строк, вычисленных без ссылки на какую-либо таблицу. Например:
mysql> SELECT 1 + 1; -> 2
При указании ключевых слов следует точно соблюдать порядок, указанный
выше. Например, выражение HAVING
должно располагаться после всех выражений
GROUP BY
и перед всеми выражениями ORDER BY
.
AS
, выражению в SELECT
можно присвоить
псевдоним. Псевдоним используется в качестве имени столбца в данном
выражении и может применяться в ORDER BY
или HAVING
. Например:
mysql> SELECT CONCAT(last_name,', ',first_name) AS full_name FROM mytable ORDER BY full_name;
WHERE
, поскольку
находящиеся в столбцах величины на момент выполнения WHERE
могут быть
еще не определены. See section A.5.4 Проблемы с alias
.
FROM table_references
задает таблицы, из которых надлежит
извлекать строки. Если указано имя более чем одной таблицы, следует
выполнить объединение. Информацию о синтаксисе объединения можно найти
в разделе section 6.4.1.1 Синтаксис оператора JOIN
. Для каждой заданной таблицы по желанию можно
указать псевдоним.
table_name [[AS] alias] [[USE INDEX (key_list)] | [IGNORE INDEX (key_list)] | FORCE INDEX (key_list)]]В версии MySQL 3.23.12 можно указывать, какие именно индексы (ключи) MySQL должен применять для извлечения информации из таблицы. Это полезно, если оператор
EXPLAIN
(выводящий информацию о структуре и порядке выполнения
запроса SELECT
), показывает, что MySQL из списка возможных индексов выбрал неправильный. Если
нужно. чтобы для поиска записи в таблице применялся только один из
возможных индексов, следует задать значение этого индекса в USE INDEX
(key_list
). Альтернативное выражение IGNORE INDEX (key_list)
запрещает
использование в MySQL данного конкретного индекса.
В MySQL 4.0.9 можно также указывать FORCE INDEX
. Это работает также, как
и USE INDEX (key_list)
но в дополнение дает понять серверу что полное
сканирование таблицы будет ОЧЕНЬ дорогостоящей операцией. Другими словами, в
этом случае сканирование таблицы будет использовано только тогда, когда не
будет найдено другого способа использовать один из данных индексов для поиска
записей в таблице.
Выражения USE/IGNORE
KEY
являются синонимами для USE/IGNORE INDEX
.
tbl_name
(в рамках текущей базы данных),
или как dbname.tbl_name
с тем, чтобы четко указать базу данных.
Ссылки на столбцы могут задаваться в виде col_name
, tbl_name.col_name
или db_name.tbl_name.col_name
. В выражениях tbl_name
или
db_name.tbl_name
нет необходимости указывать префикс для ссылок на
столбцы в команде SELECT
, если эти ссылки нельзя истолковать
неоднозначно. See section 6.1.2 Имена баз данных, таблиц, столбцов, индексы псевдонимы, где приведены примеры неоднозначных случаев, для которых
требуются более четкие определения ссылок на столбцы.
tbl_name [AS]
alias_name
:
mysql> SELECT t1.name, t2.salary FROM employee AS t1, info AS t2 WHERE t1.name = t2.name; mysql> SELECT t1.name, t2.salary FROM employee t1, info t2 WHERE t1.name = t2.name;
ORDER BY
и GROUP BY
для ссылок на столбцы, выбранные
для вывода информации, можно использовать либо имена столбцов, либо их
псевдонимы, либо их позиции (местоположения). Нумерация позиций
столбцов начинается с 1
:
mysql> SELECT college, region, seed FROM tournament ORDER BY region, seed; mysql> SELECT college, region AS r, seed AS s FROM tournament ORDER BY r, s; mysql> SELECT college, region, seed FROM tournament ORDER BY 2, 3;Для того чтобы сортировка производилась в обратном порядке, в утверждении
ORDER BY
к имени заданного столбца, в котором производится сортировка,
следует добавить ключевое слово DESC
(убывающий). По умолчанию принята
сортировка в возрастающем порядке, который можно задать явно при помощи
ключевого слова ASC
.
WHERE
можно использовать любую из функций, которая
поддерживается в MySQL. See section 6.3 Функции, используемые в операторах SELECT
и WHERE
.
Выражение HAVING
может ссылаться на любой столбец или псевдоним,
упомянутый в выражении select_expression
. HAVING
отрабатывается
последним, непосредственно перед отсылкой данных клиенту, и без какой бы
то ни было оптимизации. Не используйте это выражение для определения того, что должно
быть определено в WHERE
. Например, нельзя задать следующий оператор:
mysql> SELECT col_name FROM tbl_name HAVING col_name > 0;Вместо этого следует задавать:
mysql> SELECT col_name FROM tbl_name WHERE col_name > 0;В версии MySQL 3.22.5 или более поздней можно также писать запросы, как показано ниже:
mysql> SELECT user,MAX(salary) FROM users GROUP BY user HAVING MAX(salary)>10;В более старых версиях MySQL вместо этого можно указывать:
mysql> SELECT user,MAX(salary) AS sum FROM users GROUP BY user HAVING sum>10;
DISTINCT
, DISTINCTROW
и ALL
указывают, должны ли
возвращаться дублирующиеся записи. По умолчанию установлен параметр
(ALL
), т.е. возвращаются все встречающиеся строки. DISTINCT
и
DISTINCTROW
являются синонимами и указывают, что дублирующиеся строки
в результирующем наборе данных должны быть удалены.
SQL_
, STRAIGHT_JOIN
и HIGH_PRIORITY
,
представляют собой расширение MySQL для ANSI SQL.
HIGH_PRIORITY
содержащий его оператор SELECT
будет иметь более высокий приоритет, чем команда обновления таблицы.
Нужно только использовать этот параметр с запросами, которые должны
выполняться очень быстро и сразу. Если таблица заблокирована для
чтения, то запрос SELECT HIGH_PRIORITY
будет выполняться даже при
наличии команды обновления, ожидающей, пока таблица освободится.
SQL_BIG_RESULT
можно использовать с GROUP BY
или DISTINCT
,
чтобы сообщить оптимизатору, что результат будет содержать большое
количество строк. Если указан этот параметр, MySQL при необходимости
будет непосредственно использовать временные таблицы на диске, однако
предпочтение будет отдаваться не созданию временной таблицы с ключом
по элементам GROUP BY
, а сортировке данных.
SQL_BUFFER_RESULT
MySQL будет заносить
результат во временную таблицу. Таким образом MySQL получает
возможность раньше снять блокировку таблицы; это полезно также для
случаев, когда для посылки результата клиенту требуется значительное
время.
SQL_SMALL_RESULT
является опцией, специфической для MySQL.
Данный параметр можно использовать с GROUP BY
или DISTINCT
, чтобы
сообщить оптимизатору, что результирующий набор данных будет
небольшим. В этом случае MySQL для хранения результирующей таблицы
вместо сортировки будет использовать быстрые временные таблицы. В
версии MySQL 3.23 указывать данный параметр обычно нет необходимости.
SQL_CALC_FOUND_ROWS
(MySQL 4.0.0 и более новый) возвращает
количество строк, которые вернул бы оператор SELECT
, если бы не был
указан LIMIT
. Искомое количество строк можно получить при помощи
SELECT FOUND_ROWS()
. See section 6.3.6.2 Разные функции.
Заметьте, что в версиях MySQL до 4.1.0 это не работает с LIMIT 0
,
который оптимизирован для того, чтобы немедленно вернуть нулевой результат.
See section 5.2.8 Как MySQL оптимизирует LIMIT
.
SQL_CACHE
предписывает MySQL сохранять результат запроса в
кэше запросов при использовании QUERY_CACHE_TYPE=2
(DEMAND
).
See section 6.9 Кэш запросов в MySQL.
SQL_NO_CACHE
запрещает MySQL хранить результат запроса в
кэше запросов. See section 6.9 Кэш запросов в MySQL.
GROUP BY
строки вывода будут
сортироваться в соответствии с порядком, заданным в GROUP BY
, - так,
как если бы применялось выражение ORDER BY
для всех полей, указанных
в GROUP BY
. В MySQL выражение GROUP BY
расширено таким образом, что
для него можно также указывать параметры ASC
и DESC
:
SELECT a,COUNT(b) FROM test_table GROUP BY a DESC
GROUP BY
в MySQL обеспечивает, в частности,
возможность выбора полей, не упомянутых в выражении GROUP BY
. Если
ваш запрос не приносит ожидаемых результатов, прочтите, пожалуйста,
описание GROUP BY
. See section 6.3.7 Функции, используемые в операторах GROUP BY
.
STRAIGHT_JOIN
оптимизатор будет объединять
таблицы в том порядке, в котором они перечислены в выражении FROM
.
Применение данного параметра позволяет увеличить скорость выполнения
запроса, если оптимизатор производит объединение таблиц неоптимальным
образом. See section 5.2.1 Синтаксис оператора EXPLAIN
(получение информации о SELECT
).
LIMIT
может использоваться для ограничения количества строк,
возвращенных командой SELECT
. LIMIT
принимает один или два числовых
аргумента. Эти аргументы должны быть целочисленными константами. Если
заданы два аргумента, то первый указывает на начало первой
возвращаемой строки, а второй задает максимальное количество
возвращаемых строк. При этом смещение начальной строки равно 0
(не 1
):
Для совместимости с PostgreSQL MySQL также поддерживает синтаксис
LIMIT # OFFSET #
.
mysql> SELECT * FROM table LIMIT 5,10; # возвращает строки 6-15Для того, чтобы выбрать все строки с определенного смещения и до конца результата, вы можете использовать значение
-1
в качестве второго параметра:
mysql> SELECT * FROM table LIMIT 95,-1; # Retrieve rows 96-last.Если задан один аргумент, то он показывает максимальное количество возвращаемых строк:
mysql> SELECT * FROM table LIMIT 5; # возвращает первых 5 строкДругими словами,
LIMIT n
эквивалентно LIMIT 0,n
.
SELECT
может быть представлен в форме SELECT ... INTO
OUTFILE 'file_name'
. Эта разновидность команды осуществляет запись
выбранных строк в файл, указанный в file_name
. Данный файл создается
на сервере и до этого не должен существовать (таким образом, помимо
прочего, предотвращается разрушение таблиц и файлов, таких как
`/etc/passwd'). Для использования этой формы команды SELECT
необходимы
привилегии FILE
. Форма SELECT ... INTO OUTFILE
главным образом
предназначена для выполнения очень быстрого дампа таблицы на серверном
компьютере. Команду SELECT ... INTO OUTFILE
нельзя применять, если
необходимо создать результирующий файл на ином хосте, отличном от
серверного. В таком случае для генерации нужного файла вместо этой
команды следует использовать некоторую клиентскую программу наподобие
mysqldump --tab
или mysql -e "SELECT ..." > outfile
. Команда SELECT
... INTO OUTFILE
является дополнительной по отношению к LOAD DATA
INFILE
; синтаксис части export_options этой команды содержит те же
выражения FIELDS
и LINES
, которые используются в команде LOAD DATA
INFILE
. See section 6.4.9 Синтаксис оператора LOAD DATA INFILE
. Следует учитывать, что в
результирующем текстовом файле оператор ESCAPED BY
экранирует только
следующие символы:
ESCAPED BY
FIELDS TERMINATED BY
LINES TERMINATED BY
0
конвертируется в ESCAPED BY
, за которым
следует символ `0' (ASCII 48). Это делается потому, что необходимо
экранировать любые символы операторов FIELDS TERMINATED BY
, ESCAPED BY
или LINES TERMINATED BY
, чтобы иметь надежную возможность повторить
чтение этого файла. ASCII 0
экранируется, чтобы облегчить просмотр файла с
помощью программ вывода типа pager. Поскольку результирующий файл не
должен удовлетворять синтаксису SQL, нет необходимости экранировать
что-либо еще. Ниже приведен пример того, как получить файл в формате,
который используется многими старыми программами.
SELECT a,b,a+b INTO OUTFILE "/tmp/result.text" FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY "\n" FROM test_table;
INTO OUTFILE
использовать INTO DUMPFILE
, то MySQL
запишет в файл только одну строку без символов завершения столбцов или
строк и без какого бы то ни было экранирования. Это полезно для
хранения данных типа BLOB
в файле.
INTO OUTFILE
и
INTO DUMPFILE
, будет доступен для записи всем пользователям! Причина
этого заключается в следующем: сервер MySQL не может создавать файл,
принадлежащий только какому-либо текущему пользователю (вы никогда не
можете запустить mysqld
от пользователя root
), соответственно, файл
должен быть доступен для записи всем пользователям.
При использовании FOR UPDATE
с обработчиком таблиц, поддерживающим
блокировку страниц/строк, выбранные строки будут заблокированы для записи.
User Comments
You can simulate a CROSSTAB by the following method:-
Use IF function to select the key value of the sub table as in:
SELECT
SUM(IF(beta_idx=1, beta_value,0)) as beta1_value,
SUM(IF(beta_idx=2, beta_value,0)) as beta2_value,
SUM(IF(beta_idx=3, beta_value,0)) as beta3_value
FROM alpha JOIN beta WHERE alpha_id = beta_alpha_id;
where alpha table has the form alpha_id, alpha_blah, alpha_blah_blah
and beta table has the form beta_alpha_id, beta_other stuff,
beta_idx, beta_value
This will create 3 columns with totals of beta values according to their idx field
when selecting a single random row you have to use a query like this: SELECT ... FROM my_table ORDER BY RAND() LIMIT 1.
as explain shows, mysql optimizes this VERY badly (or may be better said, doens't optimize it at all): it uses an temporary table and an extra filesort.
couldn't this be optimized?!
if not, may be add a syntax like SELECT RANDOM_ROW .... FROM my_table ...
This method of selecting a random row should be fast:
LOCK TABLES foo READ;
SELECT FLOOR(RAND() * COUNT(*)) AS rand_row FROM foo;
SELECT * FROM foo LIMIT $rand_row, 1;
UNLOCK TABLES;
Unfortunately, variables cannot be used in the LIMIT clause, otherwise the entire thing could be done completely in SQL.
If you want to produce a CSV file of the data in a table, the following should accomplish it:
select INTO OUTFILE 'filename' fields terminated by ',' optionally enclosed by '"' escaped by '\\' from tablename;
Remember that the CSV file will be created on the box that mysql is running on. The user that mysqld is running as must have permission to create the file.
If you wish to convert the '\N' in the file which is output to some other string like 'NULL' the following perl script will do that:
#!/usr/bin/perl
while (<>) {
s/\\N/NULL/g;
print;
}
In reply to David Philips:
If your tables are not all that big, a simpler method is:
SELECT * FROM foo ORDER BY RAND(NOW()) LIMIT 1;
If it's a big table, your method will almost certainly be faster.
For previous/next navigation to find previous or next records I use the following queries:
// get previous id
$str_qry_prev="SELECT * FROM `tab_name` WHERE id < ".$current_id." ORDER by id DESC LIMIT 1"/
// get next id
$str_qry_next="SELECT * FROM `tab_name` WHERE id > ".$current_id." ORDER by id ASC LIMIT 1";
remko de knikker - caprio
http://www.szirine.com
If you need to look if there are one or more specific rows in a table or not you can speed up SELECTs on big tables.
I have a script that needs to know if there is a result (or more) or not. I had troubles with table locks.
Now I've added "LIMIT 1" and this speeded my query up a lot!
I figured this out tonight and thought it would be useful to someone. It is a way to select multiple rows without looping through code.
SELECT *
FROM products
WHERE stock_num
IN ( '3934', '3884', '3883', '3882' )
If you want to find duplicates on a field that hasn't been uniquely indexed, you can do this:
SELECT BookISBN, count(BookISBN) FROM Books GROUP BY BookISBN HAVING COUNT(BookISBN)>1;
Sometimes you want to retrieve the records that DONT match a select statement.
Consider this select:
SELECT CarIndex FROM DealerCatalog, BigCatalog WHERE
DealerCatalog.CarIndex=BigCatalog.CarIndex
This finds all the CarIndex values in the Dealer's catalog that are in the bigger distributor catalog.
How do I then find the dealer CarIndex values that ARE NOT in the bigger catalog?
The answer is to use LEFT JOIN - anything that doesn't join is given a NULL value , so we look for that:
SELECT CarIndex FROM DealerCatalog LEFT JOIN BigCatalog ON DealerCatalog.CarIndex=BigCatalog.CarIndex WHERE BigCatalog.CarIndex IS NULL
There seems to be no published known limit to the number of items, or the length therein of the IN() clause when not using subqueries.
To find double entries in a table:
SELECT db1.*
FROM tbl_data db1, tbl_data k2
WHERE db1.id <> db2.id
AND db1.name = db2.name
db1.id must be the PK
db1.name must be the fields that should be verified as double entries.
(I'm not sure wether the code is correct but in my case it works)
Johann
In order to anti-match fields by wildcards, one has to check whether the value of the field is not NULL:
For example: The table 'runs' contains 34876 rows. 205 rows have an 'info' field containing the string 'wrong'.
To select those rows for which the 'info' column does *NOT* contain the word 'wrong' one has to do:
mysql> select count(*) FROM runs WHERE info is null or info not like '%wrong%';
but not:
mysql> select count(*) FROM runs WHERE info not like %wrong%';
which would lead to a much smaller number of selected rows.
I have managed to select random records using php and MySQL like the following:
$min=1;
$row=mysql_fetch_assoc(mysql_query("SHOW TABLE STATUS LIKE 'table';"));
$max=$row["Auto_increment"];
$random_id=rand($min,$max);
$row=mysql_fetch_assoc(mysql_query("SELECT * FROM table WHERE id='$random_id'");
Voila...
Cezar
http://RO-Escorts.com
Random records without PHP, only MySQL:
select * from mailinglists order by rand() limit 1
Regards,
Geert van der Ploeg
Note that SELECT DISTINCT is case-insenstitive.
All examples about selecting random row like:
SELECT * FROM foo ORDER BY RAND() LIMIT 1;
SELECT * FROM foo ORDER BY RAND(NOW()) LIMIT 1;
are not usefull when it's about selecting a range of rows from a table.
For example, if the table has 1000 records, and we want to select one record randomly but from only 2 records from table (based on a WHERE clause), the above examples fail because the same row is returned all the time.
This is my version in this special case...
<?php
mopen();
$result=mysql_query("SELECT * FROM foo WHERE fieldx='value'");
$min=1; $max=mysql_num_rows($result);
if($max>0)
{
mysql_data_seek($result,rand($min,$max)-1);
$row=mysql_fetch_assoc($result);
echo_or_use_random_record_which_is_ $row ...
}
mclose();
?>
This code is selecting the needed rows, and picks one of the rows randomly.
Cezar
http://ro-escorts.com
Add your own comment.