SELECT语法:
SELECT
[ALL | DISTINCT | DISTINCTROW ]
[HIGH_PRIORITY]
[STRAIGHT_JOIN]
[SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
[SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
select_expr [, select_expr] ...
[into_option]
[FROM table_references
[PARTITION partition_list]]
[WHERE where_condition]
[GROUP BY {col_name | expr | position}, ... [WITH ROLLUP]]
[HAVING where_condition]
[WINDOW window_name AS (window_spec)
[, window_name AS (window_spec)] ...]
[ORDER BY {col_name | expr | position}
[ASC | DESC], ... [WITH ROLLUP]]
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
[into_option]
[FOR {UPDATE | SHARE}
[OF tbl_name [, tbl_name] ...]
[NOWAIT | SKIP LOCKED]
| LOCK IN SHARE MODE]
[into_option]
into_option: {
INTO OUTFILE 'file_name'
[CHARACTER SET charset_name]
export_options
| INTO DUMPFILE 'file_name'
| INTO var_name [, var_name] ...
}
实际工作中,来看看几个SELECT,示例1,统计某项目在活动期间的一些指标:
mysql> select count(*)祝福总数,min(wid)起始号码,max(wid)截止号码
from tb_bllottery_msg a
where not EXISTS
( select 1 from tb_lottery_prize b
where a.wid=b.wid) and FROM_UNIXTIME(a.insert_time,'%Y-%m-%d %H:%i:%S')<'2019-09-18 00:00:00';
默认情况下,UNION结果集删除重复的行,与UNION DISTINCT具有相同的效果,UNION ALL不删除重复行,并且结果包括所有SELECT语句中的所有匹配行。
示例2,通过UNION、UNION ALL来获取某活动的获奖信息表,这里SELECT字段列包括常量列,有not EXISTS、ORDER BY、LIMIT以及SUBSTRING、IFNULL函数的使用:
mysql> (select openid,'wish','4','1','Iphone X',wid,nickname,sex,headimgurl,country,city,province,unionid,
privilege,nicknameutf8 from tb_bllottery_msg a where not EXISTS
( select 1 from tb_lottery_prize b where a.wid=b.wid) and SUBSTRING(a.wid,-4)=0128 and
a.wid<=156856 order by a.wid limit 0,3)
union
(select openid,'wish','5','2','戴森吹风机',wid,nickname,sex,headimgurl,country,city,province,unionid,
privilege,nicknameutf8 from tb_bllottery_msg a where
not EXISTS ( select 1 from tb_lottery_prize b where a.wid=b.wid) and SUBSTRING(a.wid,-3)=128
and a.wid<=156856 order by a.wid limit 0,30)
union
(select openid,'wish','6','3','电饭煲',wid,nickname,sex,headimgurl,country,city,province,unionid,
privilege,nicknameutf8 from tb_bllottery_msg a where
not EXISTS ( select 1 from tb_lottery_prize b where a.wid=b.wid) and SUBSTRING(a.wid,-2)=28
and a.wid<=156856 order by a.wid limit 0,300);
################################################################
mysql> SELECT mr.openid,IFNULL(p.gamedesc,'拼图')gamedesc,IFNULL(p.gift,'未中奖')gift,mr.playdate FROM tb_ac_record mr
LEFT JOIN tb_ac_prize p
ON(mr.openid=p.openid and mr.playdate=p.prizedate and p.gametype='map') WHERE mr.openid='200282510'
UNION ALL
SELECT qr.openid,IFNULL(p.gamedesc,'答题')gamedesc,IFNULL(p.gift,'未中奖')gift,qr.playdate FROM tb_ac_record qr
LEFT JOIN tb_ac_prize p
ON(qr.openid=p.openid and qr.playdate=p.prizedate and p.gametype='qa') WHERE qr.openid='200282510'
ORDER BY gamedesc,playdate;
示例3,SELECT多表左连接:
mysql> select o.cnsino,o.npsqueryno,oi.title,oi.prcode,oi.payprice,ra.refundamount
from tb_order_refundapply ra
left join tb_order_orderitem oi on ra.orderitemid = oi.oiid
left join tb_order_orderinfo o on o.orderid = oi.orderid
where to_char(ra.createtime,'yyyyMMdd') >'20180800'
and to_char(ra.createtime,'yyyyMMdd') < '20190901'
and ra.status >0;
示例4,SELECT分组排序:
mysql> select a.cid,c.cName,a.log,a.logDate,a.createDate
from (select f.cId,f.log,f.createDate,f.logDate
from tb_kh_followlog f order by f.logDate desc
)a, tb_kh_customer c where c.Id=a.cid GROUP BY a.cId;
1. SELECT INTO
SELECT … INTO是SELECT将查询结果存储在变量或将其写入文件:
- SELECT … INTO var_list:选择列值并将其存储到变量中;
- SELECT … INTO OUTFILE:将选定的行写入文件,可以指定列和行终止符以产生特定的输出格式;
- SELECT … INTO DUMPFILE:将单行写入文件而没有任何格式。
示例:
mysql> SELECT id, data INTO @x, @y FROM test.t1 LIMIT 1;
mysql> select p.nickname,concat(u.provinceName,u.cityName,u.addr),u.mobile,p.prizedesc,p.gift
from tb_ac_prize p,tb_ac_userinfo u
where p.openid=u.openid order by p.prizedesc
INTO OUTFILE '/home/mysql/export/jjb20191227.txt';
mysql> SELECT a,b,a+b INTO OUTFILE '/tmp/result.txt'
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM test_table;
如果使用INTO DUMPFILE而不是INTO OUTFILE转储数据,则MySQL仅将一行写入文件,没有任何列或行终止符,也没有执行任何转义处理,这对于转储BLOB类型数据很有用;另外,如果表包含多个行,要使用INTO DUMPFILE需使用LIMIT 1将输出限制为单行。
2. JOIN
MySQL环境下,JOIN,CROSS JOIN和INNER JOIN是等效的(它们可以彼此替换),但在标准SQL中,它们的使用存在差异,JOIN、INNER JOIN与ON子句联合使用,CROSS JOIN是笛卡尔连接,不使用WHERE子句时,结果集是两个关联表的行的乘积。
mysql> select * from t1;
+-----+-----------+
| tid | tname |
+-----+-----------+
| 1 | 钱锺书 |
| 2 | 杨绛 |
| 3 | 路遥 |
| 6 | 鲁迅 |
| 8 | 三毛 |
+-----+-----------+
5 rows in set (0.00 sec)
mysql> select * from t2;
+-----+-----+--------------------+
| bid | tid | bookname |
+-----+-----+--------------------+
| 1 | 1 | 围城 |
| 2 | 1 | 写在人生边上 |
| 3 | 2 | 我们仨 |
| 4 | 3 | 平凡的世界 |
| 5 | 3 | 人生 |
| 6 | 4 | 挪威的森林 |
| 7 | 5 | 家书 |
+-----+-----+--------------------+
7 rows in set (0.00 sec)
mysql> SELECT * FROM t1 INNER JOIN t2 ON t1.tid = t2.tid;
+-----+-----------+-----+-----+--------------------+
| tid | tname | bid | tid | bookname |
+-----+-----------+-----+-----+--------------------+
| 1 | 钱锺书 | 1 | 1 | 围城 |
| 1 | 钱锺书 | 2 | 1 | 写在人生边上 |
| 2 | 杨绛 | 3 | 2 | 我们仨 |
| 3 | 路遥 | 4 | 3 | 平凡的世界 |
| 3 | 路遥 | 5 | 3 | 人生 |
+-----+-----------+-----+-----+--------------------+
5 rows in set (0.00 sec)
mysql> SELECT * FROM t1 JOIN t2 ON t1.tid = t2.tid;
+-----+-----------+-----+-----+--------------------+
| tid | tname | bid | tid | bookname |
+-----+-----------+-----+-----+--------------------+
| 1 | 钱锺书 | 1 | 1 | 围城 |
| 1 | 钱锺书 | 2 | 1 | 写在人生边上 |
| 2 | 杨绛 | 3 | 2 | 我们仨 |
| 3 | 路遥 | 4 | 3 | 平凡的世界 |
| 3 | 路遥 | 5 | 3 | 人生 |
+-----+-----------+-----+-----+--------------------+
5 rows in set (0.00 sec)
mysql> SELECT * FROM t1 CROSS JOIN t2 ON t1.tid = t2.tid;
+-----+-----------+-----+-----+--------------------+
| tid | tname | bid | tid | bookname |
+-----+-----------+-----+-----+--------------------+
| 1 | 钱锺书 | 1 | 1 | 围城 |
| 1 | 钱锺书 | 2 | 1 | 写在人生边上 |
| 2 | 杨绛 | 3 | 2 | 我们仨 |
| 3 | 路遥 | 4 | 3 | 平凡的世界 |
| 3 | 路遥 | 5 | 3 | 人生 |
+-----+-----------+-----+-----+--------------------+
5 rows in set (0.00 sec)
两个表间NATURAL [LEFT] JOIN语义上等效于一个INNER JOIN或一个LEFT JOIN带有USING条件;RIGHT JOIN类似于 LEFT JOIN,为了使代码可跨数据库移植,建议使用LEFT JOIN代替RIGHT JOIN。
mysql> SELECT * FROM t1 NATURAL LEFT JOIN t2;
+-----+-----------+------+--------------------+
| tid | tname | bid | bookname |
+-----+-----------+------+--------------------+
| 1 | 钱锺书 | 2 | 写在人生边上 |
| 1 | 钱锺书 | 1 | 围城 |
| 2 | 杨绛 | 3 | 我们仨 |
| 3 | 路遥 | 5 | 人生 |
| 3 | 路遥 | 4 | 平凡的世界 |
| 6 | 鲁迅 | NULL | NULL |
| 8 | 三毛 | NULL | NULL |
+-----+-----------+------+--------------------+
7 rows in set (0.00 sec)
mysql> SELECT * FROM t1 LEFT JOIN t2 ON t1.tid = t2.tid;
+-----+-----------+------+------+--------------------+
| tid | tname | bid | tid | bookname |
+-----+-----------+------+------+--------------------+
| 1 | 钱锺书 | 2 | 1 | 写在人生边上 |
| 1 | 钱锺书 | 1 | 1 | 围城 |
| 2 | 杨绛 | 3 | 2 | 我们仨 |
| 3 | 路遥 | 5 | 3 | 人生 |
| 3 | 路遥 | 4 | 3 | 平凡的世界 |
| 6 | 鲁迅 | NULL | NULL | NULL |
| 8 | 三毛 | NULL | NULL | NULL |
+-----+-----------+------+------+--------------------+
7 rows in set (0.00 sec)
mysql> SELECT * FROM t1 RIGHT JOIN t2 ON t1.tid = t2.tid;
+------+-----------+-----+-----+--------------------+
| tid | tname | bid | tid | bookname |
+------+-----------+-----+-----+--------------------+
| 1 | 钱锺书 | 1 | 1 | 围城 |
| 1 | 钱锺书 | 2 | 1 | 写在人生边上 |
| 2 | 杨绛 | 3 | 2 | 我们仨 |
| 3 | 路遥 | 4 | 3 | 平凡的世界 |
| 3 | 路遥 | 5 | 3 | 人生 |
| NULL | NULL | 6 | 4 | 挪威的森林 |
| NULL | NULL | 7 | 5 | 家书 |
+------+-----------+-----+-----+--------------------+
7 rows in set (0.00 sec)