Академический Документы
Профессиональный Документы
Культура Документы
Login | Register
• MySQL.com
• Developer Zone
• Partners & Solutions
• Customer Login
• DevZone
• Downloads
• Documentation
• Articles
• Forums
• Bugs
• Forge
• Blogs
• Documentation Library
o Table of Contents
MySQL 6.0 Reference Manual
MySQL 5.4 Reference Manual
MySQL 5.1 Reference Manual
MySQL 5.0 Reference Manual
MySQL 3.23/4.0/4.1 Manual
Search manual:
Additional languages
• French
• Spanish
MySQL 5.0 Reference Manual :: 12 SQL Statement Syntax :: 12.2 Data Manipulation
Statements :: 12.2.8 SELECT Syntax
« 12.2.7 REPLACE Syntax
12.2.8.1 JOIN Syntax »
Section Navigation [Toggle]
12.2.8. SELECT Syntax
[+/-]
SELECT is used to retrieve rows selected from one or more tables, and can include UNION
statements and subqueries. See Section 12.2.8.3, “UNION Syntax”, and Section 12.2.9,
“Subquery Syntax”.
• Each select_expr indicates a column that you want to retrieve. There must be at least
one select_expr.
• table_references indicates the table or tables from which to retrieve rows. Its syntax
is described in Section 12.2.8.1, “JOIN Syntax”.
• The WHERE clause, if given, indicates the condition or conditions that rows must satisfy to
be selected. where_condition is an expression that evaluates to true for each row to
be selected. The statement selects all rows if there is no WHERE clause.
In the WHERE clause, you can use any of the functions and operators that MySQL
supports, except for aggregate (summary) functions. See Chapter 11, Functions and
Operators.
SELECT can also be used to retrieve rows computed without reference to any table.
For example:
mysql> SELECT 1 + 1;
-> 2
You are allowed to specify DUAL as a dummy table name in situations where no tables are
referenced:
DUAL is purely for the convenience of people who require that all SELECT statements should
have FROM and possibly other clauses. MySQL may ignore the clauses. MySQL does not
require FROM DUAL if no tables are referenced.
In general, clauses used must be given in exactly the order shown in the syntax description. For
example, a HAVING clause must come after any GROUP BY clause and before any ORDER BY
clause. The exception is that the INTO clause can appear either as shown in the syntax
description or immediately following the select_expr list.
The list of select_expr terms comprises the select list that indicates which columns to
retrieve. Terms specify a column or expression or can use *-shorthand:
• A select list consisting only of a single unqualified * can be used as shorthand to select
all columns from all tables:
• SELECT * FROM t1 INNER JOIN t2 ...
• tbl_name.* can be used as a qualified shorthand to select all columns from the named
table:
• SELECT t1.*, t2.* FROM t1 INNER JOIN t2 ...
• Use of an unqualified * with other items in the select list may produce a parse error. To
avoid this problem, use a qualified tbl_name.* reference
• SELECT AVG(score), t1.* FROM t1 ...
The following list provides additional information about other SELECT clauses:
• A select_expr can be given an alias using AS alias_name. The alias is used as the
expression's column name and can be used in GROUP BY, ORDER BY, or HAVING
clauses. For example:
• SELECT CONCAT(last_name,', ',first_name) AS full_name
• FROM mytable ORDER BY full_name;
However, because the AS is optional, a subtle problem can occur if you forget the
comma between two select_expr expressions: MySQL interprets the second as an
alias name. For example, in the following statement, columnb is treated as an alias
name:
For this reason, it is good practice to be in the habit of using AS explicitly when
specifying column aliases.
It is not allowable to refer to a column alias in a WHERE clause, because the column
value might not yet be determined when the WHERE clause is executed. See
Section B.1.5.4, “Problems with Column Aliases”.
• The FROM table_references clause indicates the table or tables from which to retrieve
rows. If you name more than one table, you are performing a join. For information on join
syntax, see Section 12.2.8.1, “JOIN Syntax”. For each table specified, you can optionally
specify an alias.
• tbl_name [[AS] alias] [index_hint]
The use of index hints provides the optimizer with information about how to choose
indexes during query processing. For a description of the syntax for specifying these
hints, see Section 12.2.8.2, “Index Hint Syntax”.
To sort in reverse order, add the DESC (descending) keyword to the name of the column
in the ORDER BY clause that you are sorting by. The default is ascending order; this can
be specified explicitly using the ASC keyword.
If ORDER BY occurs within a subquery and also is applied in the outer query, the
outermost ORDER BY takes precedence. For example, results for the following statement
are sorted in descending order, not ascending order:
Use of column positions is deprecated because the syntax has been removed from the
SQL standard.
• If you use GROUP BY, output rows are sorted according to the GROUP BY columns as if
you had an ORDER BY for the same columns. To avoid the overhead of sorting that
GROUP BY produces, add ORDER BY NULL:
• SELECT a, COUNT(b) FROM test_table GROUP BY a ORDER BY NULL;
• MySQL extends the GROUP BY clause so that you can also specify ASC and DESC after
columns named in the clause:
• SELECT a, COUNT(b) FROM test_table GROUP BY a DESC;
• MySQL extends the use of GROUP BY to allow selecting fields that are not mentioned in
the GROUP BY clause. If you are not getting the results that you expect from your query,
please read the description of GROUP BY found in Section 11.11, “Functions and
Modifiers for Use with GROUP BY Clauses”.
• GROUP BY allows a WITH ROLLUP modifier. See Section 11.11.2, “GROUP BY Modifiers”.
• The HAVING clause is applied nearly last, just before items are sent to the client, with no
optimization. (LIMIT is applied after HAVING.)
A HAVING clause can refer to any column or alias named in a select_expr in the
SELECT list or in outer subqueries, and to aggregate functions. However, the SQL
standard requires that HAVING must reference only columns in the GROUP BY clause or
columns used in aggregate functions. To accommodate both standard SQL and the
MySQL-specific behavior of being able to refer columns in the SELECT list, MySQL 5.0.2
and up allows HAVING to refer to columns in the SELECT list, columns in the GROUP BY
clause, columns in outer subqueries, and to aggregate functions.
For example, the following statement works in MySQL 5.0.2 but produces an error for
earlier versions:
If the HAVING clause refers to a column that is ambiguous, a warning occurs. In the
following statement, col2 is ambiguous because it is used as both an alias and a
column name:
Preference is given to standard SQL behavior, so if a HAVING column name is used both
in GROUP BY and as an aliased column in the output column list, preference is given to
the column in the GROUP BY column.
• Do not use HAVING for items that should be in the WHERE clause. For example, do not
write the following:
• SELECT col_name FROM tbl_name HAVING col_name > 0;
• The HAVING clause can refer to aggregate functions, which the WHERE clause cannot:
• SELECT user, MAX(salary) FROM users
• GROUP BY user HAVING MAX(salary) > 10;
• MySQL allows duplicate column names. That is, there can be more than one
select_expr with the same name. This is an extension to standard SQL. Because
MySQL also allows GROUP BY and HAVING to refer to select_expr values, this can
result in an ambiguity:
• SELECT 12 AS a, a FROM t GROUP BY a;
In that statement, both columns have the name a. To ensure that the correct column is
used for grouping, use different names for each select_expr.
With two arguments, the first argument specifies the offset of the first row to return, and
the second specifies the maximum number of rows to return. The offset of the initial row
is 0 (not 1):
To retrieve all rows from a certain offset up to the end of the result set, you can use
some large number for the second parameter. This statement retrieves all rows from the
96th row to the last:
With one argument, the value specifies the number of rows to return from the beginning
of the result set:
For prepared statements, you can use placeholders (supported as of MySQL version
5.0.7). The following statements will return one row from the tbl table:
SET @a=1;
PREPARE STMT FROM 'SELECT * FROM tbl LIMIT ?';
EXECUTE STMT USING @a;
The following statements will return the second to sixth row from the tbl table:
SET @skip=1; SET @numrows=5;
PREPARE STMT FROM 'SELECT * FROM tbl LIMIT ?, ?';
EXECUTE STMT USING @skip, @numrows;
For compatibility with PostgreSQL, MySQL also supports the LIMIT row_count
OFFSET offset syntax.
If LIMIT occurs within a subquery and also is applied in the outer query, the outermost
LIMIT takes precedence. For example, the following statement produces two rows, not
one:
• A PROCEDURE clause names a procedure that should process the data in the result set.
For an example, see Section 21.3.1, “PROCEDURE ANALYSE”.
• The SELECT ... INTO OUTFILE 'file_name' form of SELECT writes the selected
rows to a file. The file is created on the server host, so you must have the FILE privilege
to use this syntax. file_name cannot be an existing file, which among other things
prevents files such as /etc/passwd and database tables from being destroyed. As of
MySQL 5.0.19, the character_set_filesystem system variable controls the
interpretation of the file name.
The SELECT ... INTO OUTFILE statement is intended primarily to let you very quickly
dump a table to a text file on the server machine. If you want to create the resulting file
on some client host other than the server host, you cannot use SELECT ... INTO
OUTFILE. In that case, you should instead use a command such as mysql -e "SELECT
..." > file_name to generate the file on the client host.
SELECT ... INTO OUTFILE is the complement of LOAD DATA INFILE; the syntax for
the export_options part of the statement consists of the same FIELDS and LINES
clauses that are used with the LOAD DATA INFILE statement. See Section 12.2.6,
“LOAD DATA INFILE Syntax”.
Column values are dumped using the binary character set. In effect, there is no
character set conversion. If a table contains columns in several character sets, the
output data file will as well and you may not be able to reload the file correctly.
FIELDS ESCAPED BY controls how to write special characters. If the FIELDS ESCAPED
BY character is not empty, it is used as a prefix that precedes following characters on
output:
The resulting file does not have to conform to SQL syntax, so nothing else need be
escaped.
If the FIELDS ESCAPED BY character is empty, no characters are escaped and NULL is
output as NULL, not \N. It is probably not a good idea to specify an empty escape
character, particularly if field values in your data contain any of the characters in the list
just given.
Here is an example that produces a file in the comma-separated values (CSV) format
used by many programs:
If you use INTO DUMPFILE instead of INTO OUTFILE, MySQL writes only one
row into the file, without any column or line termination and without performing
any escape processing. This is useful if you want to store a BLOB value in a file.
Note
Any file created by INTO OUTFILE or INTO DUMPFILE is writable by all users on
the server host. The reason for this is that the MySQL server cannot create a file
that is owned by anyone other than the user under whose account it is running.
(You should never run mysqld as root for this and other reasons.) The file thus
must be world-writable so that you can manipulate its contents.
The INTO clause can name a list of one or more variables, which can be user-
defined variables, or parameters or local variables within a stored function or
procedure body (see Section 12.8.3.3, “SELECT ... INTO Statement”). The
selected values are assigned to the variables. The number of variables must
match the number of columns. The query should return a single row. If the query
returns no rows, a warning with error code 1329 occurs (No data), and the
variable values remain unchanged. If the query returns multiple rows, error 1172
occurs (Result consisted of more than one row). If it is possible that the
statement may retrieve multiple rows, you can use LIMIT 1 to limit the result set
to a single row.
The SELECT syntax description at the beginning this section shows the INTO
clause near the end of the statement. It is also possible to use INTO immediately
following the select_expr list.
An INTO clause should not be used in a nested SELECT because such a SELECT
must return its result to the outer context.
If you use FOR UPDATE with a storage engine that uses page or row locks, rows
examined by the query are write-locked until the end of the current transaction.
Using LOCK IN SHARE MODE sets a shared lock that allows other transactions to
read the examined rows but not to update or delete them. See Section 13.2.8.3,
“SELECT ... FOR UPDATE and SELECT ... LOCK IN SHARE MODE Locking
Reads”.
Following the SELECT keyword, you can use a number of options that affect the operation of the
statement.
The ALL, DISTINCT, and DISTINCTROW options specify whether duplicate rows should be
returned. If none of these options are given, the default is ALL (all matching rows are returned).
DISTINCT and DISTINCTROW are synonyms and specify removal of duplicate rows from the
result set.
HIGH_PRIORITY, STRAIGHT_JOIN, and options beginning with SQL_ are MySQL extensions to
standard SQL.
• HIGH_PRIORITY gives the SELECT higher priority than a statement that updates a table.
You should use this only for queries that are very fast and must be done at once. A
SELECT HIGH_PRIORITY query that is issued while the table is locked for reading runs
even if there is an update statement waiting for the table to be free. This affects only
storage engines that use only table-level locking (MyISAM, MEMORY, MERGE).
HIGH_PRIORITY cannot be used with SELECT statements that are part of a UNION.
• STRAIGHT_JOIN forces the optimizer to join the tables in the order in which they are
listed in the FROM clause. You can use this to speed up a query if the optimizer joins the
tables in nonoptimal order. STRAIGHT_JOIN also can be used in the
table_references list. See Section 12.2.8.1, “JOIN Syntax”.
STRAIGHT_JOIN does not apply to any table that the optimizer treats as a const or
system table. Such a table produces a single row, is read during the optimization phase
of query execution, and references to its columns are replaced with the appropriate
column values before query execution proceeds. These tables will appear first in the
query plan displayed by EXPLAIN. See Section 7.2.1, “Optimizing Queries with
EXPLAIN”. This exception may not apply to const or system tables that are used on the
NULL-complemented side of an outer join (that is, the right-side table of a LEFT JOIN or
the left-side table of a RIGHT JOIN.
• SQL_BIG_RESULT can be used with GROUP BY or DISTINCT to tell the optimizer that the
result set has many rows. In this case, MySQL directly uses disk-based temporary tables
if needed, and prefers sorting to using a temporary table with a key on the GROUP BY
elements.
• SQL_BUFFER_RESULT forces the result to be put into a temporary table. This helps
MySQL free the table locks early and helps in cases where it takes a long time to send
the result set to the client. This option can be used only for top-level SELECT statements,
not for subqueries or following UNION.
• SQL_SMALL_RESULT can be used with GROUP BY or DISTINCT to tell the optimizer that
the result set is small. In this case, MySQL uses fast temporary tables to store the
resulting table instead of using sorting. This should not normally be needed.
• SQL_CALC_FOUND_ROWS tells MySQL to calculate how many rows there would be in the
result set, disregarding any LIMIT clause. The number of rows can then be retrieved
with SELECT FOUND_ROWS(). See Section 11.10.3, “Information Functions”.
• The SQL_CACHE and SQL_NO_CACHE options affect caching of query results in the query
cache (see Section 7.5.5, “The MySQL Query Cache”). SQL_CACHE tells MySQL to store
the result in the query cache if it is cacheable and the value of the query_cache_type
system variable is 2 or DEMAND. SQL_NO_CACHE tells MySQL not to store the result in the
query cache. For a query that uses UNION, subqueries, or views, the following rules
apply:
User Comments
Posted by Colin Nelson on February 26 2003 12:10am [Delete] [Edit]
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;
This will create 3 columns with totals of beta values according to their idx field
Posted by Corin Langosch on March 29 2003 1:49am [Delete] [Edit]
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 ...
Posted by David Phillips on April 2 2003 7:15am [Delete] [Edit]
Unfortunately, variables cannot be used in the LIMIT clause, otherwise the entire thing could be
done completely in SQL.
Posted by [name withheld] on August 20 2003 10:55pm [Delete] [Edit]
If your tables are not all that big, a simpler method is:
SELECT * FROM foo ORDER BY RAND(NOW()) LIMIT 1;
Posted by Count Henry De HavillandFortesqueSmedley on January 13 [Delete] [Edit]
2004 5:41am
If you want to find duplicates on a field that hasn't been uniquely indexed, you can do this:
Posted by Count Henry De HavillandFortesqueSmedley on January 13 [Delete] [Edit]
2004 5:59am
Sometimes you want to retrieve the records that DONT match a select statement.
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:
Posted by Johann Eckert on February 11 2004 12:14pm [Delete] [Edit]
SELECT db1.*
FROM tbl_data db1, tbl_data k2
WHERE db1.id <> db2.id
AND db1.name = db2.name
(I'm not sure wether the code is correct but in my case it works)
Johann
Posted by [name withheld] on March 2 2004 6:10am [Delete] [Edit]
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%';
+----------+
| count(*) |
+----------+
| 34671 |
+----------+
but not:
mysql> select count(*) FROM runs WHERE info not like %wrong%';
+----------+
| count(*) |
+----------+
| 5537 |
+----------+
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
Posted by Geert van der Ploeg on March 9 2004 5:44am [Delete] [Edit]
Regards,
Geert van der Ploeg
Posted by Cody Caughlan on May 26 2004 8:26pm [Delete] [Edit]
Posted by Boris Aranovich on June 9 2004 2:33pm [Delete] [Edit]
SELECT * [or any needed fileds], idx*0+RAND() as rnd_id FROM tablename ORDER BY
rnd_id LIMIT 1 [or the number of rows]
Posted by Michal Nedoszytko on August 10 2004 8:19am [Delete] [Edit]
In a database with personal information (name, surname, etc..) with an auto_increment index I
wanted to retrieve all the entries with same name and surname field (duplicate names), which by
accident were inserted to the base.
I hope this might be of help to anyone that wants to do some extended maintenance on the
database
Posted by Dmitri Mikhailov on August 24 2004 7:30pm [Delete] [Edit]
On the other hand, for this case it's simplier to engage an appropriate index if there is such:
SELECT *
FROM ccr_news
WHERE insert_date > 0;
or, if for some reason MySQL still uses a full table scan:
SELECT *
FROM ccr_news FORCE INDEX (ccr_news_insert_date_i)
WHERE insert_date > 0;
Posted by Adam Tylmad on August 25 2004 10:36am [Delete] [Edit]
Posted by Edward Hermanson on October 6 2004 6:51am [Delete] [Edit]
id name category
1 Henry Miller 2
3 June Day 1
3 Thomas Wolf 2
id category
1 Modern
2 Classics
Then just select the categories from the reference table and put
the list into a numbered array. Then in your script when you run
across a category number from the first recordset just reference
the value from the index in the second array to obtain the value.
In php in the above example it might look like:
Ed
Posted by Greg Covey on December 2 2004 11:26pm [Delete] [Edit]
The LIMIT clause can be used when you would use TOP in Access or MS SQL.
Posted by Kenan Bektas on December 14 2004 5:05pm [Delete] [Edit]
Make sure current user has (NOT) a write permission in that directory.
Posted by Kumar S on January 4 2005 8:27am [Delete] [Edit]
If You want to find the rows which are having a column with identical values then,
Regards,
Kumar.S
Posted by Hervé Pagès on February 10 2005 5:59pm [Delete] [Edit]
SELECT
...
[FROM table_references
[WHERE where_definition]
Posted by Imran Chaudhry on February 17 2005 4:13pm [Delete] [Edit]
I found a nifty way of influencing the ORDER of rows returned by a query that helps in
displaying a list with frequently accessed items at the top.
An example is a name/address form where the country is a selectable list. If most of your users
are from the UK and US you may want to do something like:
+----------+----------------------------------------+
| iso_code | name |
+----------+----------------------------------------+
| UK | United Kingdom |
| US | United States |
| AF | Afghanistan |
| AL | Albania |
| DZ | Algeria |
| AS | American Samoa |
It seems there is no way to select * from table where a certain field is distinct. In 2 sqls it is easy:
$sql9 = "SELECT DISTINCT field AS distinctfield FROM table ORDER BY distinctfield ";
$res9= $db->execute($sql9);
for($ll=0;$ll<$res9->getNumTuples();$ll++)
{
$row = $res9->getTupleDirect($ll);
$distinctfield = $row[distinctfield];
$sql8="select * from table WHERE field='distinctfield' ORDER BY distinctfield LIMIT 1";
}
Fahed
Posted by Lex Berman on February 22 2005 8:28pm [Delete] [Edit]
reply to Fahed Bizzari's post, based on Havilland-Fortesque-Smedley's comment (above) the
equivalent of select * while doing DISTINCT is:
select *, count(FIELD) from TABLE group by FIELD having count(FIELD)=1 into outfile
'foobar.txt';
then you can check the output. note that there are twice as many rows as records, because each
unique row is followed by its count (in this case count=1). so just toss the .txt file into something
and sort on the field containing the count and throw out all the rows =1. this is the same result as
a select * distinct FIELD (as far as I can tell).
Posted by Lex Berman on February 22 2005 8:32pm [Delete] [Edit]
oh, about the previous post, it's not correct because distinct should be
count(FIELD)=>1
Lex
Posted by Gregory Turner on March 10 2005 4:00pm [Delete] [Edit]
In regards to:
_______________________________________________
******************************************
I found a nifty way of influencing the ORDER of rows returned by a query that helps in
displaying a list with frequently accessed items at the top.
An example is a name/address form where the country is a selectable list. If most of your users
are from the UK and US you may want to do something like:
+----------+----------------------------------------+
| iso_code | name |
+----------+----------------------------------------+
| UK | United Kingdom |
| US | United States |
| AF | Afghanistan |
| AL | Albania |
| DZ | Algeria |
| AS | American Samoa |
_______________________________________________
******************************************
If found that if you also add in another 'iso_code' column in the order by statment after the first
one containing the IN() statment, it will sort the remaining records:
SELECT * FROM countries ORDER by iso_code IN ('UK', 'US') desc, iso_code
Posted by Heywood on March 11 2005 2:04pm [Delete] [Edit]
When using the SELECT ... INTO OUTFILE syntax, use a UNION to add headers. Here's an
example for CSV output:
This will add the text headers Fiscal Year, Location and Sales to your fields. Only caveat is with
an ORDER BY statement, if you don't want your headers sorted along with your data you need
to enclose it in parenthesis:
Posted by [name withheld] on April 21 2005 5:54pm [Delete] [Edit]
So the whole query for retrieving a whole row with one field distinct is:
Posted by Jerry Nelson on May 6 2005 6:57pm [Delete] [Edit]
As a newbie to MySQL and to dealing with BLOBs, I had a difficult time trying to determine
how to extract a BLOB field from the database back to a file. It turns out to be quite simple by
doing the following SQL:
select blobfield into dumpfile '/tmp/blobfile' from blobtable;
Posted by joel boonstra on May 12 2005 10:29pm [Delete] [Edit]
Make sure that the format of the columns that match up with your headers doesn't limit the
display of the headers. For instance, I was using the UNION tip to add a header to a column
defined as char(2) (for storing a two-letter state code). The resulting CSV file only displayed the
first two letters of my column header. The fix is simple, just use CAST() on the column in the
second SELECT to convert it to the appropriate type. In my case, doing something like this:
SELECT 'state header' FROM table UNION SELECT CAST(state AS char) FROM table INTO
OUTFILE [...]
Posted by Rene Liethof on June 8 2005 2:50pm [Delete] [Edit]
Arbitrary Ordering
If you want to use ORDER BY before GROUP BY, the only way I've found to achieve it is with
a subquery.
For example, if you want to get a list of users from a table UserActions sorted according to the
most recent action (based on a field called Time) the query would be:
Without the subquery, the group is performed first, and so the first record that appears in the
database (which is not necessarily in the order you want) will be used to determine the sort order.
This caused me huge problems as my data was in a jumbled order within the table.
--Edit--
This same result can be achieved with the use of MAX(Time), so the query would be:
As far as I can see, the subquery model still holds up if you need more complex sorting before
performing the GROUP.
Posted by Paul Montgomery on August 13 2005 8:06am [Delete] [Edit]
I've seen it asked elsewhere about how to select all duplicates, not just one row for each dupe.
Posted by Wayne Smith on November 4 2005 2:10am [Delete] [Edit]
Be careful about the "SELECT...INTO OUTFILE" options. They are similar to, but not exactly
the same as, the mysqldump options.
Two things:
1) The options in mysqldump can be in any order, because they are true command-line options
(that is, they are conceptually used together, but syntactically separate on the mysqldump
command line). The options in the SELECT...INTO OUTFILE need to be in the exact order as
specified in the documentation above.
2) The options MUST have dashes between the words (e.g., fields-enclosed-by) when use as
options with the mysqldump utility, but MUST NOT have dashes when used as options with the
SELECT...INTO OUTFILE. This may not be clear in the documentation above.
Wayne
Posted by Geoff on November 9 2005 9:22pm [Delete] [Edit]
If you want to select all fields from distinct rows why not use:
SELECT DISTINCT * FROM table GROUP BY field;
Don't forget the DISTINCT relates to the ORDER BY / GROUP BY and has nothing to do with
the 'select_expr'
Posted by Kumar MitraEndres on November 22 2005 12:51pm [Delete] [Edit]
Kumar/Germany
Posted by Flavio Ventura on December 9 2005 12:17pm [Delete] [Edit]
If you have a binary string type field and you want a case insensitive sorting you can use CAST()
as follow:
Example:
Posted by Todd Farmer on January 22 2006 6:40am [Delete] [Edit]
For large tables with auto incremented primary key values, I have found the following to be most
efficient in obtaining one random row:
Posted by Vlado Kocan on January 28 2006 10:35am [Delete] [Edit]
I prefer this way of sorting table by column values listed in another table:
The accnumber column in primary table contains ID values from ID column in the secondary
table.
Posted by LarsErik Hoffsten on March 14 2006 10:35pm [Delete] [Edit]
I havn't found a way to do it in SQL, here is a way to do it in PHP (just replace 'order_by' to the
field you want to order by):
Posted by Michal Carson on March 19 2006 5:27am [Delete] [Edit]
SELECT ... INTO OUTFILE requires the id to have the FILE privilege. That is,
As noted above, the output directory must be writable by the id under which the mysqld process
is running. Use "grep user= /etc/my.cnf " to find it.
Posted by Andrew Culver on March 20 2006 3:40pm [Delete] [Edit]
Posted by [name withheld] on March 21 2006 9:32am [Delete] [Edit]
If you want to keep field names, consider using mysqldump instead of SELECT INTO
OUTFILE.
I use this method to transfer small amounts of data from our live database to our test database,
for example when investigating a reported problem in our program code. (We cannot guarantee
the field order across all our databases.)
Posted by Zhao Xinyou on March 29 2006 3:53pm [Delete] [Edit]
when you meet more conditions, you may use the following code:
select * from yourdatabase where fieldone='value1' and fieldtwo='value2';
Posted by John Bachir on April 3 2006 10:13pm [Delete] [Edit]
Posted by Michael Heyman on April 28 2006 1:22pm [Delete] [Edit]
To select the identifiers with the greatest value in each class (where each identifier falls into one
class):
SELECT id_class,id FROM tbl,(SELECT MAX(val) AS val FROM tbl GROUP BY id_class)
AS _tbl WHERE tbl.val = _tbl.val;
We had a table logging state changes for a series of objects and wanted to find the most recent
state for each object. The "val" in our case was an auto-increment field.
This seems to be the simplest solution that runs in a reasonable amount of time.
Posted by Rich Altmaier on May 4 2006 3:24am [Delete] [Edit]
In a student signup list, use sql to find classes which are
not full. Involves combined use of RIGHT JOIN, COUNT, WHERE, GROUP BY, HAVING, and
ORDER BY.
INSERT INTO `classdescription` VALUES (2, 'firstaid', '', '2005-01-02 11:00:00', 2);
INSERT INTO `classdescription` VALUES (3, 'advanced-med', '', '2005-01-02 13:00:00', 1);
Now use RIGHT JOIN to list all class descriptions along with signups if any,
SELECT cs.s_ClassID, cs.s_PersonID, cd.ClassName, cd.ClassID, cd.ClassType, cd.ClassDate,
cd.ClassMax
from class_signups cs RIGHT JOIN
classdescription cd on (cs.s_ClassID = cd.ClassID )
in itself, not too useful, but you can see classes
having no one signed up as a NULL.
We may want to look only at the firstaid ClassType, so add a WHERE clause to
the JOIN,
SELECT cs.s_ClassID, COUNT(s_ClassID) AS ClassTotal, cd.ClassName, cd.ClassID,
cd.ClassType, cd.ClassDate, cd.ClassMax
from class_signups cs RIGHT JOIN
classdescription cd on (cs.s_ClassID = cd.ClassID ) WHERE cd.ClassType='firstaid'
GROUP BY cd.ClassID
HAVING ClassTotal < cd.ClassMax
Now there are no outputs as firstaid is full, but
suppose we are looking in this list with respect
to a certain student PersonID==12. That is, we want to see classes this person can signup
for, including the ones they are already in!
In the case we need to disregard signups by PersonID==12 for e.g.,
Posted by YI ZHANG on May 10 2006 4:27pm [Delete] [Edit]
If you cancel a long-time running query by Ctrl-C, you might find the CPU load of mysqld
remains at 99%. That's because the query is still running on mysqld, and Ctrl-C only closes the
client.
Now, you can enter mysql again and use command SHOW PROCESSLIST to check the thread
of the query, and kill the query by command KILL thread_id.
I'm using mysql 5.0.21.
Posted by Wade Bowmer on May 14 2006 11:39pm [Delete] [Edit]
Posted by Marc Grue on June 24 2006 10:44am [Delete] [Edit]
Since the LIMIT clause of a SELECT statement doesn't allow user variables you can use a
prepared statement as in the example above in the manual. An alternative is to load all record ids
of yourTable into a temporary table as shown below. This also has the benefit of getting all data
necessary for pagination of your result set:
-- insert all ids (and optional labels (for use in a page selector))
SET @a=-1;
INSERT INTO AllRows SELECT @a:=@a+1 AS rownum, id, CONCAT(first_name, ' ',
last_name) AS label FROM yourTable;
The NumberSeq table just contains the numbers 0, 1, 2, 3, ... 500 (or whatever limit you want to
set on number of pages..):
With smaller record sets the second approach is faster than the prepared statement approach.
Haven't checked speed with bigger record sets, but suspect the first approach will win then...
Hope this helps to get around the limitations of the LIMIT clause. To the MySQL team: any
plans to allow user variables in the LIMIT clause? (pleeeze!)
Posted by Rene Lopez on June 23 2006 10:19pm [Delete] [Edit]
If you want to get the record in an specific order you can do it like this
Posted by Marc Grue on June 24 2006 11:51am [Delete] [Edit]
Posted by Dennis Lindkvist on June 28 2006 8:10am [Delete] [Edit]
Althoug there is still overhead compared to "order by null" its not as bad as "order by rand()".
Posted by Chris Whitten on July 14 2006 5:21pm [Delete] [Edit]
I was trying to figure out how to sort a varchar field which contained both number string and
alphanumeric string. I wanted to sort it so that the numbers would be in order and then the
alphanumeric entries would be in order. Here is the query that helped me accomplish that:
SELECT partnum, comments , if( partnum >0, cast( partnum AS SIGNED ) , 0 ) AS numpart,
if( partnum >0, 0, partnum ) AS stringpart
FROM `part`
ORDER BY `numpart` , `stringpart`
Posted by Frank Flynn on October 6 2006 11:05pm [Delete] [Edit]
If you wish to use OUTFILE or DUMPFILE with a variable for the file name you cannot simply
put it in place - MySQL will not resolve the name.
But you can put the whole command into a variable and use "prepare" and "execute" for
example:
SELECT @myCommand := concat("SELECT * into OUTFILE
'/home/mysql/archive/daemonLog-", DATE_FORMAT(now(),'%Y%m%d-%H%i%s'), "' FROM
daemonLog");
PREPARE stmt FROM @myCommand;
EXECUTE stmt;
Posted by Michael Ekoka on November 8 2006 1:39am [Delete] [Edit]
Just my little contribution when it comes to random row selection used with mysql & php. Based
on the solution that consists of returning the count(*) of a table, then using that value to select a
random row.
The problem with that solution from the MySQL standpoint is that there still remains the
possibility of duplicate selections when we want more than one row, especially if the table is not
that large (e.g. what are the chances of getting at least 2 duplicate rows while selecting 5
randomly, 1 at a time, out of a set of 10).
My approach is to rather generate unique random numbers from php, then fetch the
corresponding table rows:
1- Use the appropriate php methods to fetch the table count from MySQL as done before:
SELECT COUNT(*) FROM foo;
2- Use php to generate some unique random numbers based on the count.
This is the php function that i use. It takes 3 arguments: the minimum and maximum range
values, and the amount of unique random numbers to be returned. It returns these numbers as an
array.
<?php
/*Array of Unique Random Numbers*/
function uniq_rand($min,$max,$size){
$randoms=array(); //this is our array
return $randoms;
}
?>
3- Once you receive your set of randoms from the above function, perform a query for each
random:
<?php
foreach($randoms as $random_row){
$query="SELECT * FROM foo LIMIT $random_row, 1;"
//perform query, retrieve values and move on to the next random row
...
}
?>
That's it
-----
On a side note regarding the php random number generation function that I have here, I'm sure
it's not the best solution all the time. For example, the closer the amount of random numbers gets
to the range of numbers available the less efficient the function gets, i.e. if you have a range of
300 numbers and you want 280 of them unique and random, the function could spend quite some
time trying to get the last 10 numbers into the array. Some probabilities get involved here, but I
suspect that it would be faster to insert the 300 numbers directly into an array, shuffle that array,
then finally select the 280 first entries and return them.
Also, as pointed earlier in the thread, keep in mind that if your table isn't that large, just
performing the following works very well (e.g. selecting 5 random rows on a moderately large
table):
SELECT * FROM foo ORDER BY RAND() LIMIT 5;
Posted by Rustam Valiev on November 17 2006 7:50am [Delete] [Edit]
If you want use multilanguage queryies you cat use this:
Table 1
--------------
langid langname
--------------
1 rus
2 eng
3 den
---------------
Table 2 (catalog)
-----------------------
catid url
-----------------------
1 www.google.com
2 www.yandex.ru
3 www.mysql.com
------------------------
table 3 (titles of sites from Table 3)
-------------------------------------
langid catid title
-------------------------------------
1 1 Poiskovaya sistema
2 1 Search system
1 2 Portal
2 2 Portal
3 2 Portal
1 3 Sayt razrabotchikov MySQL
2 3 Site of MySQL's team
3 3 Bla bla bla
------------------------------------
And you need select sites from table2 on any language (for example Denmark), but site
google.com have not title by Denmark. Ok if you can't select title by current language, you
should select title by default language (here russian). You can make in one query
SELECT *, (
SELECT title
FROM table3
WHERE table3.catid = table2.catid AND langid = 3
UNION
SELECT title
FROM table3
WHERE table3.catid = table2.catid AND langid = 1
LIMIT 1
) as title
FROM table2
It very easy, but i think it query very big for MySQL if table2 contain around 1000-5000 rows,
and site have 5000-6000 people per second.
Now my task more complexed, i need select any site from table2 :
1 - On current language
2 - If site have not title, Select title by default language
3 - If site have not title on default, Select title by any language.
I think if will make it by thats method - it will very big for MySQL.
Posted by Ray Perea on December 8 2006 8:57pm [Delete] [Edit]
In regards to:
Posted by Count Henry De Havilland-Fortesque-Smedley on January 13 2004 5:59am
--------------START QUOTE---------------------
Sometimes you want to retrieve the records that DONT match a select statement.
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:
I have found that the Left Join is quite expensive when doing this type of SQL Query. It is great
if you have less than 1000 records in each table that you want to compare. But the real hardship
is realized when you have 100,000 records in each table. Trying to do this type of join takes
forever because each and every record in 1 table has to be compared to each and every record in
the other table. In the case of 100,000 records, MySQL will do 10 BILLION comparisons (from
what I have read, I may be mistaken).
So I tried the sql query above to see which rows in 1 table do not have a corresponding value in
the other table. (Note that each table had close to 100,000 rows) I waited for 10 minutes and the
Query was still going. I have since came up with a better way that works for me and I hope it
will work for someone else. Here goes....
1: You must create another field in your base table. Let's call the new field `linked` (For the
example above, we would perform this query ---ONLY ONCE--- to create the linked field in the
DealerCatalog table.)
2: Now to get your results, simply execute the following queries instead of the left join query
stated above
I know it is 3 queries instead of 1 but I am able to achieve the same result with 100K rows in
each table in about 3 seconds instead of 10 minutes (That is just how long I waited until I gave
up. Who knows how long it actually takes) using the LEFT JOIN method.
I would like to see if anyone else has a better way of dealing with this type of situation. I have
been looking for a better solution for a few years now. I haven't tried MySQL 5 yet to see if there
is a way to maybe create a view to deal with this situation but I suspect MySQL developers know
about the expensive LEFT JOIN....IS NULL situation on large tables and are doing something
about it.
Posted by Frederic Theriault on December 8 2006 10:26pm [Delete] [Edit]
Make sure you don't use stored functions in your WHERE clause if it is not necessary.
For our search feature, we needed to get an id using a stored function. Since it was in the
WHERE clause, it reprocesses the function for every row! This could turn out to be pretty heavy.
Posted by Héctor Hugo Huergo on April 19 2007 2:12pm [Delete] [Edit]
Hi! I'm using SELECT ... INTO OUTFILE. First I´ve permissions problems. Add to the user the
FILE privileges... AND RESTART THE DAEMON :). Bye
Posted by Will Jaspers on May 4 2007 9:36pm [Delete] [Edit]
For anyone utilizing two or more tables to create select boxes, I've finally (and painstakingly)
found a way to check if the item is selected.
-- Query
SELECT
s.`state_code`,
s.`state_name`,
IF(state_id IN
(SELECT d2s.state_id
FROM drove_to_states d2s
WHERE driver_id = '%u'
), 1, null)
`selected`
FROM `states` s,
ORDER BY `state_name` ASC;
Using PHP's sprintf command, we can create a select field using this query:
<?php
[...]
$driver_id = 1;
define("QUERY", (SEE ABOVE) );
define("OPTION",'<option value="%s"%s>%s</option>');
$query = mysql_query(sprintf(QUERY, $driver_id), $connect);
echo '<select>';
while(list($code,$state,$selected) = mysql_fetch_row($query))
{
$selected = is_null($selected) ? null : ' selected';
echo sprintf(OPTION, $code, $selected, $state);
}
echo '</select>';
[...]
?>
Posted by Martin Sarfy on August 14 2007 7:58pm [Delete] [Edit]
SELECT INTO OUTFILE creates world-writable files. To avoid this security risk, you can
create new subdirectory with +x rights for mysql and your user only (e.g. using chown me:mysql
restricted_dir, chmod 770 restricted_dir), and then save the file into this directory. This way only
you and mysql process can modify the file.
Posted by Dan Bogdan on October 27 2007 4:28pm [Delete] [Edit]
If you want to copy a file from the server in other location you can use
select load_file('source_file') into OUTFILE 'target_file'
Security issue on windows ... you can copy any file from any folder even if you don't have access
to that file
to an convenient folder where you have access !!
Posted by Drazen Djurisic on November 13 2007 5:39pm [Delete] [Edit]
If you need names from second table for more then 1 columns in first table.
Select
table1.id,
table1.konto,
table2.name as name1,
table1.konto1,
table2_2.name as name2,
table1.konto3,
table2_3.naziv as name3,
from table1
left join table2 on (table1.konto=table2.id)
left join table2 as table2_2 on (table1.konto2=table2_2.id)
left join table2 as table2_3 on (table1.konto3=table2_3.id)
Posted by Rich Altmaier on February 16 2008 8:01pm [Delete] [Edit]
As a variant on the random row selection question, I had the goal of reading out a limited set of
rows, always in the same order, but starting at a different point in the sequence each time (like
Facebook short list of members):
e.g. given records a, b, c, d, e, f
I want random selections of triplets such as:
b, c, d
c, d, e
f, a, b --> note I want wraparound!
As a variant on the random row selection question, I had the goal of reading out a limited set of
rows, always in the same order, but starting at a different point in the sequence each time (like
Facebook short list of members):
e.g. given records a, b, c, d, e, f
I want random selections of triplets such as:
b, c, d
c, d, e
f, a, b --> note I want wraparound!
Posted by Michael Yakobi on March 6 2008 8:32am [Delete] [Edit]
| Objects Attributes
+----+------+------+ +-------+-----+-------+
| id | type | name | | objId | key | value |
+====+======+======+ +=======+=====+=======+
| 1 | T1 | O1 | | 1 | K1 | V1 |
| 2 | T2 | O2 | | 1 | K2 | V2 |
| 3 | T1 | O3 | | 2 | K3 | V3 |
| 4 | T2 | O4 | | 2 | K4 | V4 |
| | 2 | K5 | V5 |
| | 3 | K1 | V6 |
| | 3 | K2 | V7 |
The common approach for selecting the attributes of each object into a single result-row per
object is to join Objects with Attributes multiple times. However, not only such SELECT can
grow very big and ugly, with large tables it becomes very slow.
This could be dealt with using group-by functions, so to select all the objects of type T1, use the
following SQL:
| SELECT
| o.id,
| o.name,
| MAX(IF(a.key='K1', a.value, null)) as K1,
| MAX(IF(a.key='K2', a.value, null)) as K2
| FROM
| Objects o,
| Attributes a
| WHERE
| o.id = a.objid and
| o.type = 'T1'
| GROUP BY
| a.id
The result will be:
+----+------+----+----+
| id | name | K1 | K2 |
+====+======+====+====+
| 1 | O1 | V1 | V2 |
| 3 | O3 | V6 | V7 |
Posted by Wiebe Cazemier on March 25 2008 7:17pm [Delete] [Edit]
For those who don't fully understand the concept of joins, I wrote an article which might help.
http://www.halfgaar.net/sql-joins-are-easy
Posted by Sam on April 8 2008 4:49pm [Delete] [Edit]
I just spent a few hours figuring this one out and there doesn't seem to be much info online about
it so I thought I'd share.
You should use the following syntax to create a CSV file in the format expected by Microsoft
Excel:
... INTO OUTFILE '/temp.csv' FIELDS ESCAPED BY '""' TERMINATED BY ',' ENCLOSED
BY '"' LINES TERMINATED BY '\r\n';
However fields with carriage returns may break the CSV as MySQL will automatically close a
field when the \r\n line break is found. To work around this, replace all \r\n breaks with \n. The
field does not close on \n breaks and it will be read into a single cell in Excel. You can do this in
the same SQL statement, for example:
Note: this replaces NULL values with an empty string which is technically not the same thing
but it will give you an empty cell in Excel instead of breaking the CSV structure and shifting the
following cells to the left.
Posted by Paris Alex on October 1 2008 10:29am [Delete] [Edit]
To create a SELECT statement that categorize and label its result set according to special rules,
try this...
SELECT 'cheap' AS priceCat, productName productCount FROM MyProducts WHERE price <
1000
UNION
SELECT 'moderate' AS priceCat, productName FROM MyProducts WHERE price >= 1000
AND price <2000
UNION
SELECT 'expensive' AS priceCat, productName FROM MyProducts WHERE price >= 2000
It essentially returns a two column result set. The first column contains the word 'cheap',
'moderate' or 'expensive' depending on the price of the product. The second column is the
product name. This query can easily be modified to return a count of number of products
categorized by the price range:
SELECT 'cheap' AS priceCat, COUNT(*) productCount FROM MyProducts WHERE price <
1000
UNION
SELECT 'moderate' AS priceCat, COUNT(*) FROM MyProducts WHERE price >= 1000 AND
price <2000
UNION
SELECT 'expensive' AS priceCat, COUNT(*) FROM MyProducts WHERE price >= 2000
It may sound like an obvious thing the an experienced SQL guy, but I think this tip will be useful
to a beginner. Hope this tip helps a SQL developer soon! ;-)
Paris
http://www.loveparishotel.com/