- 查出本网站,最新的(goods_id最大)的商品
select goods_id,goods_name,cat_id from goods order by goods_id desc limit 1;
- 查出本网站,最新的(goods_id最大)的商品,不能用排序方法
select goods_id,goods_name,cat_id,max(goods_id) from goods having goods_id=33;
这里是我们已知最大的goods_id是33,但如果我们不知道呢,所以,我们需要用一个表返回最大的goods_id:select max(goods_id) from goods;
然后用where判断goods_id与查出来的最大值相等:
select goods_id,goods_name,cat_id,max(goods_id) from goods where goods_id=(select max(goods_id) from goods);
- 总结:
以后凡需要查出最新商品,先用max()查出最大的goods_id,然后在根据goods_id查询商品
就是以后商品表再怎么边,delect max()语句的返回值,始终是指向最大的goods_id的
查出每个栏目下的最新(goods_id最大)的商品
- 用where子查询解:
第一步,先求出每个栏目下的最大的goods_id:
select max(goods_id),cat_id from goods group by cat_id order by cat_id asc;
第二步,我们只要把goods_id=(16,32,18...28)这几个商品取出来
select goods_id,goods_name,shop_price,cat_id from goods where goods_id in (select max(goods_id) from goods group by cat_id order by cat_id asc);
- 用from子查询解
select goods_id,cat_id,goods_name from goods order by cat_id asc,goods_id desc;
select * from (select goods_id,cat_id,goods_name from goods order by cat_id asc,goods_id desc) as tmp group by cat_id;
子查询类型:
- where型子查询:把内层查询的结果作为外层查询的比较条件,
典型题:查询最大商品、最贵商品
所以
特点:
如果where 列=(内层 sql),则内层sql返回的必是单行单列,单个值
如果where 列 in (内层 sql),则内层sql只返回单列,可以多行 - from型子查询
【注】查询结果集在结果上可以当成表看
内层sql的查询结果,当成一张临时表,供外层sql,再次查询 - existe型子查询
是指 把外层sql的结果,拿到内层sql去测试,如果内层sql成立,则该行取出
建一个category表:
mysql> select * from category;
+--------+-------------------+-----------+
| cat_id | cat_name | parent_id |
+--------+-------------------+-----------+
| 1 | 手机类型 | 0 |
| 2 | CDMA手机 | 1 |
| 3 | GSM手机 | 1 |
| 4 | 3G手机 | 1 |
| 5 | 双模手机 | 1 |
| 6 | 手机配件 | 0 |
| 7 | 充电器 | 6 |
| 8 | 耳机 | 6 |
| 9 | 电池 | 6 |
| 11 | 读卡器和内存卡 | 6 |
| 12 | 充值卡 | 0 |
| 13 | 小灵通/固话充值卡 | 12 |
| 14 | 移动手机充值卡 | 12 |
| 15 | 联通手机充值卡 | 12 |
+--------+-------------------+-----------+
14 rows in set (0.03 sec)
要求:别把14个栏目都取出来,只把下面有商品的栏目取出来
思路:设某栏目cat_id为N,则select * from goods where cat_id=N
能取出数据,则说明该栏目有商品
select cat_id,cat_name from category where exists (select * from goods where goods.cat_id=category.cat_id);
建表语句解析:
- 建表时,列后面not null default '',default 0,是什么意思?
答:就是让这个列不为null,如果某个列确实没值,也有默认值,也不为null - 为什么不希望列的值为null?
判断字符串是否为null
select lisi=null;
select null=null;
delect null!=null;
以上三句的返回值都是NULL
我们知道,null是空,若要和他进行比较,需要用到特殊的运算符:is null,is not null
答:
A:不好比较:
null是一种类型,比较时,只能用专门的is null和is not null来比较,碰到运算符,一律返回null
B:效率不高:
影响索引效率
因此,在建表时,我们一般采用
not null default ""/0;
表与集合的关系:
一张表就是一个集合
每一行就是一个元素
集合有唯一性,所以一张表里面不可能有数据完全相同的一行,这个由mysql内部控制
- 两个集合相乘:
mysql> create table test10 (
-> id int,
-> sname char(20)
-> )engine myisam charset utf8;
Query OK, 0 rows affected (0.14 sec)
mysql> create table test11 (
-> id int,
-> sname char(20)
-> )engine myisam charset utf8;
Query OK, 0 rows affected (0.02 sec)
mysql> set names gbk;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into test10
-> values ,
-> (1,'云彩'),
-> (2,'月亮'),
-> (3,'星星1');
Query OK, 3 rows affected (0.10 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> insert into test11
-> values ,
-> (95,'猴子'),
-> (96,'老虎');
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from test10,test11;
+------+-------+------+-------+
| id | sname | id | sname |
+------+-------+------+-------+
| 1 | 云彩 | 95 | 猴子 |
| 1 | 云彩 | 96 | 老虎 |
| 2 | 月亮 | 95 | 猴子 |
| 2 | 月亮 | 96 | 老虎 |
| 3 | 星星1 | 95 | 猴子 |
| 3 | 星星1 | 96 | 老虎 |
+------+-------+------+-------+
6 rows in set (0.01 sec)
左连接的语法:
假设A表在左,不动,B表在A表的右边滑动
A表与B表通过一个关系来筛选B表的行
语法:
A left join B on 条件
——条件为真,则B对应的行取出
【注】A left join B,并不是说A表的就一定在左边,只是说在查询数据时,以A表为准,显示的数据顺序是根据自己select
后面的内容指定的,如:select sname,id from A left join B on ...
A left join B on 条件
这一块形成的也是一个结果集,可以看成一张表,设为C
既如此,可以对 C表作查询,自然where,group,order by,limit,,having等等都可以使用
问:C表可以查询的列有哪些列?
答:A,B的列都可以查
mysql> select goods_name,goods_id,goods_number,cat_name,shop_price from goods left join category on goods.cat_id = category.cat_id;
+------------------------------+----------+--------------+-------------------+------------+
| goods_name | goods_id | goods_number | cat_name | shop_price |
+------------------------------+----------+--------------+-------------------+------------+
| kd876 | 1 | 1 | 3G手机 | 1388.00 |
| 诺基亚n85原装充电器 | 4 | 17 | 耳机 | 58.00 |
| 诺基亚原装5800耳机 | 3 | 24 | 耳机 | 68.00 |
| 索爱原装m2卡读卡器 | 5 | 8 | 读卡器和内存卡 | 20.00 |
| 胜创kingmax内存卡 | 6 | 15 | 读卡器和内存卡 | 42.00 |
| 诺基亚n85原装立体声耳机hs-82 | 7 | 20 | 耳机 | 100.00 |
| 飞利浦9@9v | 8 | 1 | GSM手机 | 399.00 |
| 诺基亚e66 | 9 | 4 | GSM手机 | 2298.00 |
| 索爱c702c | 10 | 7 | GSM手机 | 1328.00 |
| 索爱c702c | 11 | 1 | GSM手机 | 1300.00 |
| 摩托罗拉a810 | 12 | 8 | GSM手机 | 983.00 |
| 诺基亚5320 xpressmusic | 13 | 8 | GSM手机 | 1311.00 |
| 诺基亚5800xm | 14 | 1 | 3G手机 | 2625.00 |
| 摩托罗拉a810 | 15 | 3 | GSM手机 | 788.00 |
| 恒基伟业g101 | 16 | 0 | CDMA手机 | 823.33 |
| 夏新n7 | 17 | 1 | GSM手机 | 2300.00 |
| 夏新t5 | 18 | 1 | 3G手机 | 2878.00 |
| 三星sgh-f258 | 19 | 12 | GSM手机 | 858.00 |
| 三星bc01 | 20 | 12 | GSM手机 | 280.00 |
| 金立 a30 | 21 | 40 | GSM手机 | 2000.00 |
| 多普达touch hd | 22 | 1 | GSM手机 | 5999.00 |
| 诺基亚n96 | 23 | 8 | 双模手机 | 3700.00 |
| p806 | 24 | 100 | GSM手机 | 2000.00 |
| 小灵通/固话50元充值卡 | 25 | 2 | 小灵通/固话充值卡 | 48.00 |
| 小灵通/固话20元充值卡 | 26 | 2 | 小灵通/固话充值卡 | 19.00 |
| 联通100元充值卡 | 27 | 2 | 联通手机充值卡 | 95.00 |
| 联通50元充值卡 | 28 | 0 | 联通手机充值卡 | 45.00 |
| 移动100元充值卡 | 29 | 0 | 移动手机充值卡 | 90.00 |
| 移动20元充值卡 | 30 | 9 | 移动手机充值卡 | 18.00 |
| 摩托罗拉e8 | 31 | 1 | GSM手机 | 1337.00 |
| 诺基亚n85 | 32 | 4 | GSM手机 | 3010.00 |
+------------------------------+----------+--------------+-------------------+------------+
31 rows in set (0.00 sec)
左连接之后的表也可以用where等语句:
mysql> select goods_name,goods_id,goods_number,cat_name,goods.cat_id,shop_price from goods left join category on goods.cat_id = category.cat_id where goods.cat_id = 4;
+--------------+----------+--------------+----------+--------+------------+
| goods_name | goods_id | goods_number | cat_name | cat_id | shop_price |
+--------------+----------+--------------+----------+--------+------------+
| kd876 | 1 | 1 | 3G手机 | 4 | 1388.00 |
| 诺基亚5800xm | 14 | 1 | 3G手机 | 4 | 2625.00 |
| 夏新t5 | 18 | 1 | 3G手机 | 4 | 2878.00 |
+--------------+----------+--------------+----------+--------+------------+
3 rows in set (0.02 sec)
左连接、右连接、内连接的区别:
- 左右连接是可以互换的:
A left join B = B right join A
【注】既然左右连接可以互换,尽量用左连接,出于移植时兼容性方面的考虑 - 内连接的特点
A inner join B
A inner join B
和left join/right join
的关系:
内连接是左右连接的交集
【注】mysql中不支持外连接
小练习
Match的hostTeamID与guestTeamID都与Team中的teamID关联
查出2006-6-1到2006-7-1之间的所有比赛,并且用一下形式列出:
拜仁 2:0 不来梅 2006-6-21
- 建表
create table m (
mid int ,
hid int,
gid int,
mres varchar(10),
matime date
)engine myisam charset utf8;
create table t(
tid int,
tname varchar(20)
)engine myisam charset utf8;
【注】match为mysql的关键字
mysql> create table match (
-> mid int ,
-> hid int,
-> gid int,
-> mres varchar(10),
-> matime date
-> )engine myisam charset utf8;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'match (
mid int ,
hid int,
gid int,
mres varchar(10),
matime date
)engine myisam' at line 1
- 解题:
#将id与name关联
mysql> select hid,t1.tname,mres,gid,t2.tname,matime
-> from
-> (m left join t as t1 on hid=t1.tid)
-> left join t as t2 on gid=t2.tid;
+------+----------+------+------+----------+------------+
| hid | tname | mres | gid | tname | matime |
+------+----------+------+------+----------+------------+
| 1 | 国安 | 2:0 | 2 | 申花 | 2006-05-21 |
| 2 | 申花 | 1:2 | 3 | 布尔联队 | 2006-06-21 |
| 3 | 布尔联队 | 2:5 | 1 | 国安 | 2006-06-25 |
| 2 | 申花 | 3:2 | 1 | 国安 | 2006-07-21 |
+------+----------+------+------+----------+------------+
4 rows in set (0.00 sec)
#最终结果
mysql> select hid,t1.tname,mres,gid,t2.tname,matime
-> from
-> (m left join t as t1 on hid=t1.tid)
-> left join t as t2 on gid=t2.tid
-> where matime between '2006-06-01' and '2006-07-01';
+------+----------+------+------+----------+------------+
| hid | tname | mres | gid | tname | matime |
+------+----------+------+------+----------+------------+
| 2 | 申花 | 1:2 | 3 | 布尔联队 | 2006-06-21 |
| 3 | 布尔联队 | 2:5 | 1 | 国安 | 2006-06-25 |
+------+----------+------+------+----------+------------+
2 rows in set (0.36 sec)
33集
网友评论