|
最近,在做一个项目的时候,发现得出的数据于预料的相差很多,仔细的研究了一下,发现问题出在 distinct语句和groupy by,order by 首先,distinct语句,获得非重复的(唯一)行记. grouy by是分组,order by 是排序。 直接看我的例子。
假定我有一个表f_job,有字段:
select job_id, com_id,job_time from f_job order by job_time desc limit 10; \T e:\web\web\PHP\fhr\tee.txt +--------+--------+---------------------+ job_id com_id job_time +--------+--------+---------------------+ 5060 2205 2006-09-29 16:30:11 4707 19084 2006-09-29 16:27:55 4708 19084 2006-09-29 16:27:55 4709 19084 2006-09-29 16:27:55 4710 19084 2006-09-29 16:27:55 4711 19084 2006-09-29 16:27:55 4859 19084 2006-09-29 16:27:55 4918 19084 2006-09-29 16:27:55 5059 2205 2006-09-29 16:27:22 4078 2715 2006-09-29 16:18:36 +--------+--------+---------------------+ 10 rows in set (0.03 sec)
还有其他字段,不可能影响结果.此处不列出。
job_id是primary key。 com_id是外键,我需要按照时间来排序。所以必须使用order by!
你看到了com_id在得出的结果中不唯一,对,我需要的结果就是提取com_id唯一的最近10条com_id的记录,而已。 我就以以前的MSSQL的经验写如下的语句执行:
mysql> select distinct( com_id) from f_job order by job_time desc limit 10; \T e:\web\web\php\fhr\tee.txt +--------+ com_id +--------+ 19084 2197 19917 19580 19520 19664 19397 19900 1176 19449 +--------+对,这次得出的结果是唯一,但是,这不对呀,很明显,把com_id记录号码是2005的记录给没了,这结果肯定错。马上分析一下所有的的结果,发现忽略的com_id并没有消失,只是被排到后面去了。
我按照时间排序,应该出现的结果第一个就是2205呀,为什么能排到后面?从两条可疑记录看出了结果:
原记录:
5058 19580 2006-09-29 15:23:58 5057 19917 2006-09-29 15:14:16 4973 19580 2006-09-29 15:13:49 5011 19580 2006-09-29 15:13:49
distinct后的次序:
19917 19580
这说明,对于不是在一起的隔行记录,如果恰巧隔一行,还可以被order by 比较出来,否则比较出来的不再真实,这是因为,被缓存的上次的order by 的临时值在客观上不再有用!还有一种情况,如果记录连着,也可以被比较出来。
先是明白了MySql的弱智了。 马上又执行了一下操作,结果如下: mysql> select distinct(com_id),job_time from f_job order by job_time desc limit 10; +--------+---------------------+ com_id job_time +--------+---------------------+ 2205 2006-09-29 16:30:11 19084 2006-09-29 16:27:55 2205 2006-09-29 16:27:22 2715 2006-09-29 16:18:36 2197 2006-09-29 16:03:16 19580 2006-09-29 15:23:58 19917 2006-09-29 15:14:16 19580 2006-09-29 15:13:49 19520 2006-09-29 10:29:41 19900 2006-09-29 10:16:48 +--------+---------------------+ 10 rows in set (0.10 sec)
先和这个比较一下: mysql> select com_id,job_time from f_job order by job_time desc limit 10; \T e:\web\web\php\fhr\tee.txt +--------+---------------------+ com_id job_time +--------+---------------------+ 2205 2006-09-29 16:30:11 19084 2006-09-29 16:27:55 19084 2006-09-29 16:27:55 19084 2006-09-29 16:27:55 19084 2006-09-29 16:27:55 19084 2006-09-29 16:27:55 2006-09-29 16:27:55 19084 2006-09-29 16:27:55 2205 2006-09-29 16:27:22 2715 2006-09-29 16:18:36 +--------+---------------------+ 10 rows in set (0.06 sec)
发现,distinct恰巧和前面第一次测试的结果相反处理我们的信息,他把隔行的看作不同的结果输出,这就导致了2205的记录又出现了。 然后我就用了group by语句,应该可以吧,结果也让我。。。:
mysql> select com_id from f_job group by com_id order by job_time desc limit 10; +--------+ com_id +--------+ 19084 2197 19917 19580 19520 19664 19397 19900 1176 19449 +--------+ 10 rows in set (0.03 sec)
这和distinct的结果一样,这倒不出乎意料,然后我又加入分组job_time,看看:
mysql> select com_id from f_job group by com_id,job_time order by job_time desc limit 10; +--------+ com_id +--------+ 2205 19084 2205 2715 2197 19580 19917 19580 19520 19900 +--------+ 10 rows in set (0.03 sec)
这结果差一点点了,然后我再distinct(com_id)一下,应该可以了吧!看看:
mysql> select distinct(com_id) from f_job group by com_id,job_time order by job_time desc limit 10; \T e:\web\web\php\fhr\tee.txt +--------+ com_id +--------+ 19084 2197 19917 19580 19520 19664 19397 19900 1176 19449 +--------+ 10 rows in set (0.04 sec)
汗,这和没加group by 的一点区别都没,怎么这样弱呀!没办法,这怎么办,犹豫中。。。
上面的问题彻底的说明了这样一个事实:distinct只能返回它的目标字段,而无法返回其它字段。。。
汗,这和没加group by 的一点区别都没,怎么这样弱呀!没办法,这怎么办,犹豫中。。。 想起了一个很能骚的一个人--phzzy,这jh,QQ说了句话,果然在,他玩php,马上求助,经过1个多小时的艰苦YY,终于这鸟人先大爷我一步给出语句:
select (`com_id`),max(`job_time`) from `f_job` GROUP BY `com_id` order by max(`job_time`) limit 10;
mdgb,终于明白了,刚拿到这语句就明白了。
我tmd知道这是2次排序,md,group by是一次,然后无论怎么样,都不可能2次排序,因为第二次必须借助内部的集聚函数。。。。。。我怎么没想到max,气死我了。
|