欢迎访问 ‘ 数据库 ’ 的所有文章

ThinkinLAMP聚会

上周六参加了ThinkinLAMP 在浦东的聚会 ,主要是去听 <MYSQL自动化运维>的
下面是文档链接.

庄浩英:《MySQL自动化监控》 – Thinking In LAMP 2011年2月聚会分享

[slideshare id=6999348&doc=mysql-110221060130-phpapp01]

锅巴:《菜菜子的移动互联观 – iOS Tech Talks 2011 参会感悟》 – Thinking In LAMP 2011年2月聚会分享

郭佳:《网页游戏开发与敏捷开发》 – Thinking In LAMP 2011年2月聚会分享

ThinkinLAMP 已经有很多期的聚会, 往期都在thinkinlamp.com官方有分享文档,视频. 大家可以去看看,

JOIN联表中ON,WHERE后面跟条件的区别

对于JOIN的连表操作,这里就不细述了,当我们在对表进行JOIN关联操作时,对于ON和WHERE后面的条件,不清楚大家有没有注意过,有什么区别,可能有的朋友会认为跟在它们后面的条件是一样的,你可以跟在ON后面,如果愿意,也可以跟在WHERE后面。它们在ON和WHERE后面究竟有一个什么样的区别呢?
在JOIN操作里,有几种情况。LEFT JOIN,RIGHT JOIN,INNER JOIN等。

为了清楚的表达主题所描述的问题,我简要的对LEFT,RIGHT,INNER这几种连接方式作一个说明。

下面就拿一个普通的博客系统的日志表(post)和分类表(category)来描述吧。

这里我们规定有的日志可能没有分类,有的分类可能目前没有属于它的文章。

1.    LEFT JOIN:

(保证找出左联表中的所有行)

查出所有文章,并显示出他们的分类: 

SELECT p.title,c.category_name FROM post p LEFT JOIN category c ON p.cid = c.cid2.    RIGHT JOIN:

(保证找出右联表中的所有行)

查询所有的分类,并显示出该分类所含有的文章数。 

SELECT COUNT(p.id),c.category_name FROM post p RIGHTJOIN  category c ON p.pid = c.cid3.    INNER JOIN

(找出两表中关联相等的行)

查询有所属分类的日志。(即那些没有所性分类的日志文章将不要我们的查询范围之内)。 

SELECT p.title,c.category_name FROM post p INNER JOIN category c ON p.cid = c.cid.

这种情况和直接两表硬关联等价。

现在我们回过头来看上面的问题。

对于第一种情况,如果我们所ON 的条件写在WHERE 后面,将会出现什么情况呢?

即: 

SELECT p.title,c.category_name FROM post p LEFT JOIN category c WHERE  p.cid = c.cid

对于第二种情况,我们同样按照上面的书写方式。 

SELECT COUNT(p.id),c.category_name FROM post p RIGHTJOIN  category c WHERE p.pid = c.cid

如果运行上面的SQL语句,就会发现,它们已经过滤掉了一些不满足条件的记录,可能在这里,大家会产生疑问了,不是用了LEFT和RIGHT吗?它们可以保证左边或者右边的所有行被全部查询出来,为什么现在不管用了呢?对于出现这种的问题,呵呵!是不是觉得有些不可思议。

出现这种的问题,原因就在WHERE和ON这两个关键字后面跟条件。

好了,现在我也不调大家味口了,给大家提示答案吧。

对于JOIN参与的表的关联操作,如果需要不满足连接条件的行也在我们的查询范围内的话,我们就必需把连接条件放在ON后面,而不能放在WHERE后面,如果我们把连接条件放在了WHERE后面,那么所有的LEFT,RIGHT,等这些操作将不起任何作用,对于这种情况,它的效果就完全等同于INNER连接。对于那些不影响选择行的条件,放在ON或者WHERE后面就可以。

记住:所有的连接条件都必需要放在ON后面,不然前面的所有LEFT,和RIGHT关联将作为摆设,而不起任何作用。

sql中on、where、having的区别

on、where、having这三个都可以加条件的子句中,on是最先执行,where次之,having最后。有时候如果这先后顺序不影响中间结果的话,那最终结果是相同的。但因为on是先把不符合条件的记录过滤后才进行统计,它就可以减少中间运算要处理的数据,按理说应该速度是最快的。  
   
   根据上面的分析,可以知道where也应该比having快点的,因为它过滤数据后才进行sum,所以having是最慢的。但也不是说having没用,因为有时在步骤3还没出来都不知道那个记录才符合要求时,就要用having了。  
   
   在两个表联接时才用on的,所以在一个表的时候,就剩下where跟having比较了。在这单表查询统计的情况下,如果要过滤的条件没有涉及到要计算字段,那它们的结果是一样的,只是where可以使用rushmore技术,而having就不能,在速度上后者要慢。  
   
   如果要涉及到计算的字段,就表示在没计算之前,这个字段的值是不确定的,根据上篇写的工作流程,where的作用时间是在计算之前就完成的,而having就是在计算后才起作用的,所以在这种情况下,两者的结果会不同。  
   
   在多表联接查询时,on比where更早起作用。系统首先根据各个表之间的联接条件,把多个表合成一个临时表后,再由where进行过滤,然后再计算,计算完后再由having进行过滤。由此可见,要想过滤条件起到正确的作用,首先要明白这个条件应该在什么时候起作用,然后再决定放在那里

mysql关联left join条件on和where条件的区别

想了解一下 left join 后面 on  where 能不能同时 使用 ,找到了下面的这篇文章,觉得

能让我很好的理解这个问题。

现有两个表,商品表(products)和sales_detail(销售记录表)。如下图:

products:
pid pname pcode
1   商品1   AC90
2   商品2 DE78
3   商品3    XXXX

sales_detail:
aid pcode saletime
1   AC90 2008-09-22
2   DE78 2008-09-22
3   AC90 2008-09-23
4   AC90 2008-09-24

按商品在某个时间段内的销售量来排行,比如我想统计23-24号这两天的销售数量并排行。(注:DE78这个商品在这两天没有销售,但是也要显示出来,只是数量为0)。

– 表的结构 `products`

CREATE TABLE `products` (
`pid` int(3) NOT NULL auto_increment,
`pname` varchar(20) NOT NULL,
`pcode` varchar(20) NOT NULL,
PRIMARY KEY   (`pid`)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

– 导出表中的数据 `products`

INSERT INTO `products` (`pid`, `pname`, `pcode`) VALUES (1, ‘商品1′, ‘AC90′),
(2, ‘商品2′, ‘DE78′),
(3, ‘商品3′. ‘XXXX’);
– ——————————————————–

– 表的结构 `sales_detail`

CREATE TABLE `sales_detail` (
`aid` int(3) NOT NULL auto_increment,
`pcode` varchar(20) NOT NULL,
`saletime` date NOT NULL,
PRIMARY KEY   (`aid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

– 导出表中的数据 `sales_detail`

INSERT INTO `sales_detail` (`aid`, `pcode`, `saletime`) VALUES (1, ‘AC90′, ’2008-09-22′),
(2, ‘DE78′, ’2008-09-22′),
(3, ‘AC90′, ’2008-09-23′),
(4, ‘AC90′, ’2008-09-24′);

区别两条sql语句:
阅读全文

MYSQl left join 联合查询

MYSQl left join 联合查询效率分析

user表:

代码:
id | name
———
1 | libk
2 | zyfon
3 | daodao

user_action表:

代码:
user_id | action
—————
1 | jump
1 | kick
1 | jump
2 | run
4 | swim

sql:

代码:
select id, name, action from user as u
left join user_action a on u.id = a.user_id

result:

代码:
id | name | action
——————————–
1 | libk | jump ①
1 | libk | kick ②
1 | libk | jump ③
2 | zyfon | run ④
3 | daodao | null ⑤

分析:
注意到user_action中还有一个user_id=4, action=swim的纪录,但是没有在结果中出现,
而user表中的id=3, name=daodao的用户在user_action中没有相应的纪录,但是却出现在了结果集中
因为现在是left join,所有的工作以left为准.
结果1,2,3,4都是既在左表又在右表的纪录,5是只在左表,不在右表的纪录
结论:
我们可以想象left join 是这样工作的
从左表读出一条,选出所有与on匹配的右表纪录(n条)进行连接,形成n条纪录(包括重复的行,如:结果1和结果3),
如果右边没有与on条件匹配的表,那连接的字段都是null.
然后继续读下一条。
引申:
我们可以用右表没有on匹配则显示null的规律, 来找出所有在左表,不在右表的纪录, 注意用来判断的那列必须声明为not null的。
如:

sql:

代码:
select id, name, action from user as u
left join user_action a on u.id = a.user_id
where a.user_id is NULL

(注意:1.列值为null应该用is null 而不能用=NULL
2.这里a.user_id 列必须声明为 NOT NULL 的)

代码:
result:
id | name | action
————————–
3 | daodao | NULL
——————————————————————————–

Tips:
1. on a.c1 = b.c1 等同于 using(c1)
2. INNER JOIN 和 , (逗号) 在语义上是等同的
3. 当 MySQL 在从一个表中检索信息时,你可以提示它选择了哪一个索引。
如果 EXPLAIN 显示 MySQL 使用了可能的索引列表中错误的索引,这个特性将是很有用的。
通过指定 USE INDEX (key_list),你可以告诉 MySQL 使用可能的索引中最合适的一个索引在表中查找记录行。
可选的二选一句法 IGNORE INDEX (key_list) 可被用于告诉 MySQL 不使用特定的索引。
4. 一些例子:

使用sql语句将一个表中的数据拷贝到另一个表中

声名:a,b ,都是表
--b表存在(两表结构一样)
INSERT INTO b SELECT * FROM a
若两表只是有部分(字段)相同,则
INSERT INTO b(col1,col2,col3,col4,...) SELECT col1,col2,col3,col4,... FROM a WHERE...
把表a插入到表b中去。
--b表不存在
CREATE TABLE b AS SELECT *  FROM a;(mysql用这条)
SELECT * INTO b FROM a
//
CREATE TABLE b AS SELECT (字段1,字段2...) FROM a;(mysql用这条)

SELECT (字段1,字段2...) INTO b FROM a