8.3 Examples of common queriesHere follows examples of how to solve some common problems with MySQL. Some of the examples uses the table 'shop' holds the prices of each article (item number) for certain traders. Supposing that each trader has a single fixed price per article, then (item, trader) is a primary key for the records. You can create the example table as: 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); Okay, so the example data is: 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 | +---------+--------+-------+ 8.3.1 The maximum value for column"What's the highest item number?" SELECT MAX(article) AS article FROM shop +---------+ | article | +---------+ | 4 | +---------+ 8.3.2 The row holding the maximum of a certain column"Find number, dealer, and price of the most expensive article" In ANSI-SQL this is easily done with a sub-query: SELECT article, dealer, price FROM shop WHERE price=(SELECT MAX(price) FROM shop) In MySQL (not having sub-selects yet) just do it in two steps:
Another solution is to sort all rows descending by price and only
get the first row using the MySQL specific SELECT article, dealer, price FROM shop ORDER BY price DESC LIMIT 1
Note: If there are several most expensive articles (e.g. each 19.95)
the 8.3.3 Maximum of column: per group: only the values"What's the highest price per article?" 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 | +---------+-------+ 8.3.4 The rows holding the group-wise maximum of a certain field"For each article find the dealer(s) with the most expensive price."
In SELECT article, dealer, price FROM shop s1 WHERE price=(SELECT MAX(s2.price) FROM shop s2 WHERE s1.article = s2.article) In MySQL it's best do it in several steps:
This can easily be done with a temporary table: CREATE TEMPORARY TABLE tmp ( article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL, price DOUBLE(16,2) DEFAULT '0.00' NOT NULL); LOCK TABLES article read; INSERT INTO tmp SELECT article, MAX(price) FROM shop GROUP BY article; SELECT article, dealer, price FROM shop, tmp WHERE shop.article=tmp.articel AND shop.price=tmp.price; UNLOCK TABLES; DROP TABLE tmp;
If you don't use a "Can it be done with a single query?" Yes, but only by using a quite inefficient trick that I call the "MAX-CONCAT trick": 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 | +---------+--------+-------+ The last example can of course be made a bit more efficient by doing the splitting of the concatenated column in the client. 8.3.5 Using foreign keysOne doesn't need foreign keys to join 2 tables.
The only thing CREATE TABLE persons ( id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, name CHAR(60) NOT NULL, PRIMARY KEY (id) ); CREATE TABLE shirts ( id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, style ENUM('t-shirt', 'polo', 'dress') NOT NULL, color ENUM('red', 'blue', 'orange', 'white', 'black') NOT NULL, owner SMALLINT UNSIGNED NOT NULL REFERENCES persons, PRIMARY KEY (id) ); INSERT INTO persons VALUES (NULL, 'Antonio Paz'); INSERT INTO shirts VALUES (NULL, 'polo', 'blue', LAST_INSERT_ID()), (NULL, 'dress', 'white', LAST_INSERT_ID()), (NULL, 't-shirt', 'blue', LAST_INSERT_ID()); INSERT INTO persons VALUES (NULL, 'Lilliana Angelovska'); INSERT INTO shirts VALUES (NULL, 'dress', 'orange', LAST_INSERT_ID()), (NULL, 'polo', 'red', LAST_INSERT_ID()), (NULL, 'dress', 'blue', LAST_INSERT_ID()), (NULL, 't-shirt', 'white', LAST_INSERT_ID()); SELECT * FROM persons; +----+---------------------+ | id | name | +----+---------------------+ | 1 | Antonio Paz | | 2 | Lilliana Angelovska | +----+---------------------+ SELECT * FROM shirts; +----+---------+--------+-------+ | id | style | color | owner | +----+---------+--------+-------+ | 1 | polo | blue | 1 | | 2 | dress | white | 1 | | 3 | t-shirt | blue | 1 | | 4 | dress | orange | 2 | | 5 | polo | red | 2 | | 6 | dress | blue | 2 | | 7 | t-shirt | white | 2 | +----+---------+--------+-------+ SELECT s.* FROM persons p, shirts s WHERE p.name LIKE 'Lilliana%' AND s.owner = p.id AND s.color <> 'white'; +----+-------+--------+-------+ | id | style | color | owner | +----+-------+--------+-------+ | 4 | dress | orange | 2 | | 5 | polo | red | 2 | | 6 | dress | blue | 2 | +----+-------+--------+-------+ |