技术开发 频道

与你预想的不一样的MySQL的10件事

  #6. NOT IN和NULL值

SELECT  a.*  
FROM    a  
WHERE   a.column
NOT IN        
         (          
        
SELECT column        
         FROM    b          
          )

 

  如果在b.column中有一个NULL值,那么这个查询是不会返回任何结果的。和其他谓词一样,IN 和 NOT IN 遇到NULL也会被判定为NULL。

  你应该使用NOT EXISTS重写这个查询:

SELECT  a.*  
FROM    a  
WHERE  
NOT EXISTS        
       (          
        
SELECT NULL        
        FROM    b        
        WHERE   b.column
= a.column      
        )

 

  不像IN,EXISTS总是被判定为true或false的。

  #5. 对随机的样本进行排序

SELECT  *  
FROM    a  
ORDER BY        
       RAND(), column
LIMIT
10

 

  这个查询试图选出10个随机的记录,按照column来排序。

  ORDER BY会按照自然顺序来对输出结果进行排序:这就是说,当第一个表达式的值相等的时候,这些记录才会按照第二个表达式来排序。

  但是,RAND()的结果是随机的。要让RAND()的值相等是行不通的,所以,按照RAND()排序以后,再按照column来排序也是没有意义的。

  要对随机的样本记录进行排序,可以使用这个查询:

SELECT  *  
FROM    
(          
SELECT  *          
FROM    mytable          
ORDER BY                
RAND()          
LIMIT
10        
) q  
ORDER BY        
column

 

  #4. 通过一个组来选取任意的记录

SELECT  DISTINCT(grouper), a.*  
FROM    a

 

  这个查询打算通过某个组(定义为grouper来)来选出一些记录

  DISTINCT不是一个函数,它是SELECT子句的一部分。它会应用到SELECT列表中的所有列,实际上,这里的括号是可以省略的。所以,这个查询可能会选出grouper中的值都相同的记录(如果在其他列中,至少有一个列的值是不同的)。

  有时,这个查询可以正常地使用( 这主要依赖于MySQL对GROUP BY的扩展):

SELECT  a.*  
FROM    a  
GROUP BY        
grouper

 

  在某个组中返回的非聚合的列可以被任意地使用。

  首先,这似乎是一个很好的解决方案,但是,它存在着一个很严重的缺陷。它依赖于这样一个假设:虽然可以通过组来任意地获取,但是返回的所有值都要属于一条记录。

  虽然当前的实现似乎就是这样的,但是它并没有文档化,无论何时,它都有可能被改变(尤其是,当MySQL学会了在GROUP BY的后面使用index_union的时候)。所以依赖于这个行为并不安全。

  如果MySQL支持分析函数的话,这个查询可以很容易地用另一种更清晰的方式来重写。但是,如果这张表拥有一个PRIMARY KEY的话,即使不使用分析函数,也可以做到这一点:

SELECT  a.*  
FROM    (          
SELECT  DISTINCT grouper        
FROM    a          
) ao  
JOIN   a  
ON      a.id =          
       (          
        
SELECT  id        
         FROM    a ai          
         WHERE   ai.grouper
= ao.grouper          
         LIMIT
1        
       )

 

0
相关文章