MySQL-Cookbook

前言

其实一直感觉自己的MySQL十分弱逼,因为用的Laravel,同时也因为自己没怎么看过MySQL基础方面的东西。所以,趁现在有一点时间,就找了这本MySQL-Cookbook来看。这是O`Reilly的第二版,最新的是第三版,但是没有找到资源。
现在将书中我认为作用大的示例语句摘出来,如果对这些语句有疑问,可以查阅Cookbook。

正文

注意

  1. 聚类函数(COUNT等等)会忽略NULL,如果一张表里面总共有7条记录,而这里面包含3条有字段为NULL的记录,那么使用聚类函数的时候只会计算4条记录。COUNT()函数对待空值与其他聚类函数略有不同,COUNT(*)计算时会包含空值,而COUNT(column_name)时不会计算NULL。
  2. 语句分号结尾!分号结尾!分号结尾!或者也可以用“\c”。
  3. 当面对在某个表中寻找与另一个表不匹配(即另一个表所缺少)的值的问题时,你应该养成如此的思维习惯,“啊,这是一个LEFT JOIN问题”。
  4. USING和HAVING。USING用于表连接时给定连接条件,必须是两个表是通过同名字段连接才能使用USING(书中没有明确说明必须是这样)。SELECT * FROM table1 JOIN table2 ON table1.id = table2.id等于SELECT * FROM table1 JOIN table2 USING(id)。引入HAVING是因为WHERE不能和统计函数一起使用,SELECT customer, SUM(price) FROM order GROUP BY customer HAVING SUM(price)<2000

第三章:从表中查找数据

SELECT * FROM mail
查询表中所有数据

SELECT t, srcuser, srchost, dstuser, dsthost FROM mail
查询结果只输出特定列(这样可以给结果排序,并且可以精简查询结果)

SELECT t, srcuser, srchost FROM mail WHERE srchost = 'venus'
特定条件查询

SELECT * FROM mail WHERE srcuser LIKE 's%'
模糊条件查询

SELECT * FROM mail WHERE srcuser = 'barb' AND dstuser = 'tricia'
多重条件查询

SELECT CONCAT(MONTHNAME(t), '', DAYOFMONTH(t), ', ', YEAR(t)), srcuser, size FROM mail
CONCAT,串连接

SELECT DATE_FORMAT(t, '%M %e, %Y'), srcuser, size FROM mail
DATE_FORMAT函数

SELECT '1+1+1' AS 'The expression, 1+1+1 AS 'The result'
AS,别名

SELECT DATE_FORMAT(t, '%M %e, %Y') AS Date_sent, CONCAT(srcuser, '@', srchost) AS Sender, CONCAT(dstuser, '@', dsthost) AS Recipient, size FROM mail
CONCAT和AS的联合使用

SELECT t, srcuser, dstuser, size/1024 AS Kilobytes FROM mail WHERE size/1024 > 500
WHERE子句中不能使用别名,应使用原始别名(此例中即应使用size/1024,而不能使用Kilobytes)

SELECT srcuser, srcuser < 'c', size, size > 5000 FROM mail

SELECT DISTINCT srcuser FROM mail
DISTINCT,查询唯一化

SELECT DISTINCT YEAR(t), MONTH(t), DAYOFMONTH(t) FROM mail
对函数处理后的数据进行唯一化

SELECT COUNT(DISTINCT srcuser) FROM mail
COUNT+DISTINCT

SELECT * FROM taxpayer WHERE id IS NOT NULL
NULL值的处理

SELECT name, IF(id IS NULL, 'Unknow', id) AS 'Id' FROM taxpayer

SELECT name, IFNULL(id, 'Unknow') AS 'Id' FROM taxpayer
IFNULL

SELECT * FROM mail WHERE size > 100000 ORDER BY size
ORDER BY

SELECT * FROM mail WHERE dstuser = 'reicia' ORDER BY srcuser, srchost
WHERE+ORDER BY

SELECT * FROM mail WHERE size > 50000 ORDER BY size DESC
ORDER BY DESC

CREATE VIEW view_mail AS SELECT DATE_FORMAT(t, '%M %e, %Y') AS Date_sent, CONCAT(srcuser, '@', srchost) AS Sender, CONCAT(dstuser, '@', dsthost) AS Recipient, size FROM mail
SELECT * FROM view_mail
视图,CREATE VIEW

SELECT id, name, service, contact_name FROM profile INNER JOIN profile_contact ON id = profile_id
初见INNER JOIN

SELECT * FROM profile_contact WHERE profile_id = (SELECT id FROM profile WHERE name = 'Mort')
WHERE子句中使用子句

SELECT * FROM profile LIMIT 5
初见LIMIT

SELECT * FROM profile ORDER BY birth DESC LIMIT 1
LIMIT放在ORDER BY后面

SELECT * FROM profile LIMIT 4,2
从原始结果集跳过4条记录,取随后的2条

SELECT * FROM al_winner WHERE wins > 15 ORDER BY wins DESC LIMIT 5
LIMIT的混合使用

SELECT name, wins FROM al_winner WHERE wins >= (SELECT DISTINCT wins FROM al_winner ORDER BY wins DESC, name LIMIT 3,1) ORDER BY wins DESC, name
查询生日的最后4个,并要求结果集按生日升序排列

SELECT * FROM (SELECT name, birth FROM profile ORDER BY birth DESC LIMIT 4) AS t ORDER BY birth
选出最新的4个,再将他们升序排列(其实也可以计算出总长度,升序排列后取出最后4个)

CREATE TABLE mail2 LIKE mail
克隆表

INSERT INTO mail2 SELECT * FROM mail WHERE srcuser = 'barb'

SELECT thing, UPPER(thing), LOWER(thing) FROM limbs
字符串大小写转换

SELECT * FROM driver_log ORDER BY name, trav_date
ORDER BY

SELECT t, srcuser, FLOOR((size + 1023) / 1024) AS Kilobytes FROM mail WHERE size > 50000 ORDER BY Kilobytes
AS+ORDER BY

SELECT name, jersey_num FROM roster ORDER BY jersey_num + 0
这里的jersey_num是一个数字,也可能是一个 写作了字串的数字,所以在排序的时候“+ 0”将其变成数字

SELECT t, CONCAT(srcuser, '@', srchost) AS Sender, size FROM mail WHERE size > 50000 ORDER BY srchost, srcuser
WHERE + ORDER BY

SELECT DAYNAME(date) AS Day, date, description FROM event ORDER BY DAYOFWEEK(date)
按周历排序,以Sunday为第一天

SELECT DAYNAME(date), date, description FROM event ORDER BY MOD(DAYOFWEEK(date) + 5, 7)
按周历排序,以Monday为第一天

SELECT id, MID(id, 4, 5) AS Serial, LEFT(id, 3) AS Category, RIGHT(id, 2) AS Country FROM housewares
函数:MID + LEFT + RIGHT

SELECT id, LEFT(SUBSTRING(id, 4), CHAR_LENGTH(SUBSTRING(id, 4) - 2)) FROM housewares2
函数:CHAR_LENGTH

SELECT name, SUBSTRING_INDEX(SUBSTRING_INDEX(name, '.', -3), '.', 1) AS Leftmost, SUBSTRING_INDEX(SUBSTRING_INDEX(name, '.', -2), '.', 1) AS Middle, SUBSTRING_INDEX(name, '.', -1) AS Rightmost FROM hostname
函数:SUBSTRING_INDEX,网址按域名排序(www.baidu.com,不精准)

SELECT name, SUBSTRING_UNDEX(SUBSTRING_INDEX(CONCAT('.', name), '.', -3), '.', 1) AS Leftmost, SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT('.', name), '.', -2), '.', 1) AS Middle, SUBSTRING_INDEX(name, '.', -1) AS Rightmost FROM hostname
网址按域名排序,较精准

SELECT t, srcuser, dstuser, size FROM mail GROUP BY FIELD (name, 'Henry', 'Suzi', 'Ben')
用户自定义排序

SELECT TABLE_ROWS FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'cookbook' AND TABLE_NAME = 'states'
从INFORMATION_SHCEMA表中查询cookbook库下面的states表一共有多少行

SELECT COUNT(*) FROM states WHERE statehood < '1900-01-01'
20世纪初,美国有多少个州

SELECT COUNT(*) FROM states WHERE statehood BETWEEN '1800-01-01' AND '1899-12-31'
美国有多少个州是19世纪加入联邦的

SELECT COUNT(IF(DAYOFWEEK(trav_date) IN (1, 7), 1, NULL)) AS 'Weekend trips', COUNT(IF(DAYOFWEEK(trav_date) IN (1, 7), NULL, 1)) AS 'Weekday trips' FROM driver_logs
计算周末和周中行程的对比

SELECT = MIN(t) AS Earliest, MAX(t) AS Latest, MIN(size) AS Smallest, MAX(size) AS Largest FROM mail
函数:MIN + MAX + SUM + AVG

SELECT DISTINCT name FROM driver_log ORDER BY name
一共有多少位司机

SELECT DISTINCT HOUR(t) AS Hour FROM mail ORDER BY Hour
函数+DISTINCT

SET @max = (SELECT MAX(pop) FROM states) SELECT pop AS 'Highest population', name FROM states WHERE pop = @max
查询人口最多的州

SELECT pop AS 'Highest population', name FROM states WHERE pop = (SELECT MAX(pop) FROM states)
查询人口最多的州

SELECT srcuser, srchost, COUNT(srcuser) FROM mail GROUP BY srcuser, srchost
COUNT是对GROUP BY后的子群进行的计算

SELECT srcuser, MAX(size), MAX(t) FROM mail GROUP BY srcuser
MAX都是对GROUP BY后的子群进行的计算

SELECT srcuser, dstuser, MAX(size) FROM mail GROUP BY srcuser, dstuser
查找mail列表中每一对发送者和接收者之间发送的最大的信息

SELECT name, trav_date, MAX(miles) AS 'Longest trip' FROM driver_log GROUP BY name
错误方式示例:查询每个司机最长的旅程,及其发生的日期。下面是正确方法
CREATE TABLE t SELECT name, MAX(miles) AS miles FROM driver_log GROUP BY name; SELECT d.name, d.trav_date, d.miles AS 'Longest trip' FROM driver_log AS d INNER JOIN t USING (name, miles) ORDER BY name

SELECT trav_date, COUNT(trav_date) FROM driver_log GROUP BY trav_date HAVING COUNT(trav_date) = 1
哪一天仅有一个司机当班

SELECT CHAR_LENGTH(name), COUNT(*) FROM states GROUP BY CHAR_LENGTH(name)
州名称长度的分布

SELECT * FROM artist, painting
两个表的全连接,笛卡尔积

SELECT * FROM artist, painting WHERE artist.a_id = painting.a_id
SELECT * FROM artist INNER JOIN painting ON artist.a_id = painting.a_id
SELECT * FROM artist INNER JOIN painting USING(a_id)
上面三句表达的意思是一样的

SELECT * FROM artist INNER JOIN painting USING(a_id) WHERE painting.state = 'KY'
查询在肯塔基州购买的画作。根据经验规则,通常使用ON或USING来指定如何连接表,而使用WHERE子句限定选择哪些已连接的行

SELECT artist.name, painting.title, states.name, painting.price FROM artist INNER JOIN painting INNER JOIN states ON artist.a_id = painting.a_id AND painting.state = states.abbrev
三个表的连接查询

SELECT artist.name, COUNT(*) AS 'Number of paintings' FROM artist INNER JOIN painting ON artist.a_id = painting.a_id GROUP BY artist.name
对于每个画家各收藏了多少作品

SELECT artist.name, COUNT(*) AS 'Number of paintings', SUM(painting.price) AS 'Total price', AVG(painting.price) AS 'Average price' FROM artist INNER JOIN painting ON artist.a_id = painting.a_id GROUP BY artist.name
函数+INNER JOIN

SELECT * FROM artist LEFT JOIN painting ON artist.a_id = painting.a_id
初见外连接

SELECT artist.* FROM artist LEFT JOIN painting ON artist.a_id = painting.a_id WHERE painting.a_id IS NUL
只显示在artist表中,却不被painting表所拥有的值

SELECT artist.name, IF(COUNT(painting.a_id) > 0, 'Yes', 'No') AS 'In collection' FROM painting RIGHT JOIN artist ON artist.a_id = painting.a_id GROUP BY artist.name

SELECT p2.title FROM painting AS p1 INNER JOIN painting AS p2 ON p1.a_id = p2.a_id WHERE p1.title = 'The Potato Eaters'
一张表与自身连接

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容