sql多关键字匹配,优先权显示的算法

http://hi.baidu.com/%CB%AD%BB%E1%D4%DA%CE%D2%CA%D6%D0%C4/blog/item/de1b0c38d9068827b8998f2a.html

 

假设只有一个table,名为pages,有四个字段,id, url,title,body。里面储存了很多网页,网页的url地址,title和网页的内容,然后你用一个sql查询将url匹配的排在最 前,title匹配的其次,body匹配最后,没有任何字段匹配的,不返回。

就是上面这道面试题,让我想了一个下午,在网上找资料,最后用下面方法实现
SELECT *
FROM page where url like ‘%baidu%’ or title like ‘%baidu%’ or like ”
ORDER BY CHARINDEX(‘baidu’, url) DESC, CHARINDEX(‘baidu’, title) DESC,
CHARINDEX(‘baidu’, body) DESC

但我感觉这种方法并不是最简单的,后来把这个方法发给面试的人,他给我了一种更简单方法,只要用基本的Sql语句就可以实现。代码如下

 

select a.[id],a.mark from
(
select [page].[id],100 as mark from [page] where [page].[url] like ‘%baidu%’
union
select [page].[id],50 as mark from [page] where [page].[title] like ‘%baidu%’
union
select [page].[id],10 as mark from [page] where [page].[body] like ‘%baidu%’
) as a   order by mark desc

用union 实现联合查询,在每个查询语句中定义一个临时变量mark 并给mark赋值,在最后的输出时采用mark来排序,这样实现真的好简单。其实这都考验我们对Sql的编程思想。

变更wordpress博客域名时数据库所需修改

文件全部由根目录(http://www.laozhao.info)移动到子目录blog/中,数据库做以下修改:

表wp_options:
siteurl对应value改为http://zduo.me/blog/,
home对应value改为http://www.laozhao.info

表wp_posts:
update wp_posts set guid=replace(guid,’zduo.me/’,’zduo.me/blog/’)
update wp_posts set post_content=replace(post_content,’zduo.me/’,’zduo.me/blog/’)

The database could not be exclusively locked to perform the operation(SQL Server 5030错误解决办法)

SQL Server 5030错误解决办法

今天在使用SQL Server时,由于之前创建数据库忘记了设置Collocation,数据库中插入中文字符都是乱码,于是到DataBase的Options中修改Collocation,出现了The database could not be exclusively locked to perform the operation这个错误,无法修改字符集为Chinese_PRC_90_CI_AS。

解决办法找了很久才找到,如下:

1.执行SQL ALTER DATABASE db_database SET SINGLE_USER WITH ROLLBACK IMMEDIATE

修改为单用户模式

2.然后关闭所有的查询窗口,修改Options的Collocation属性为Chinese_PRC_90_CI_AS

3.执行SQL ALTER DATABASE db_database SET MULTI_USER

再修改为多用户模式

Discuz联表查询优化

引用地址:http://tuibian.com/?p=707

discuz中viewthread.php是用来读取一个话题内相关帖子的程序,相关的sql语句大概为:

SELECT p.*, m.uid, m.username, m.groupid, m.regdate, m.lastactivity, m.posts, m.digestposts, m.oltime,
                m.pageviews, m.credits, m.extcredits1, m.extcredits2, m.extcredits3, m.extcredits4, m.extcredits5, m.extcredits6,
                m.extcredits7, m.extcredits8, m.email, m.gender, m.showemail, m.invisible, m.avatarshowid, m.xspacestatus, mf.nickname, mf.site,
                mf.icq, mf.qq, mf.yahoo, mf.msn, mf.taobao, mf.alipay, mf.location, mf.medals, mf.avatar, mf.avatarwidth,
                mf.avatarheight, mf.sightml AS signature, mf.customstatus
                FROM {$tablepre}posts p
                LEFT JOIN {$tablepre}members m ON m.uid=p.authorid
                LEFT JOIN {$tablepre}memberfields mf ON mf.uid=m.uid
                WHERE p.tid=’TID’ AND p.invisible=’0′ ORDER BY dateline LIMIT 60

这个语句中采用了两个left join查询,如果先查询posts表,然后再查询members和memberfields表是不是会速度更快呢:

程序1:采用完全的联表查询:

query("SELECT p.*, m.uid, m.username, m.groupid, m.regdate, m.lastactivity, m.posts, m.digestposts, m.oltime,
                m.pageviews, m.credits, m.extcredits1, m.extcredits2, m.extcredits3, m.extcredits4, m.extcredits5, m.extcredits6,
                m.extcredits7, m.extcredits8, m.email, m.gender, m.showemail, m.invisible, m.avatarshowid, m.xspacestatus, mf.nickname, mf.site,
                mf.icq, mf.qq, mf.yahoo, mf.msn, mf.taobao, mf.alipay, mf.location, mf.medals, mf.avatar, mf.avatarwidth,
                mf.avatarheight, mf.sightml AS signature, mf.customstatus
                FROM {$tablepre}posts p
                LEFT JOIN {$tablepre}members m ON m.uid=p.authorid
                LEFT JOIN {$tablepre}memberfields mf ON mf.uid=m.uid
                WHERE p.tid=’$i’ AND p.invisible=’0′ ORDER BY dateline LIMIT 60");
    
    while($post = $db->fetch_array($query)) {
        
        //do somthing;
    }
}
$mtime = explode(‘ ‘, microtime());        
$runtime = ($mtime[1] + $mtime[0] – $discuz_starttime);
?>

程序读tid从395000到398770的所有话题,运行8次,运行时间分别为:
19.4085040092 16.5643789768 13.6189751625 14.2483608723 14.4175901413 14.3845379353 17.1536540985 17.2402610779
可以看到运行两三次后mysql的query cache开始生效,速度逐渐稳定在14秒左右

程序2:先读取相关cdb_posts中的数据,再用联表查询用户的信息。

query("SELECT * FROM {$tablepre}posts WHERE tid=’$i’ AND invisible=’0′ ORDER BY dateline LIMIT 60");
    while ($post = $db->fetch_array($query))
    {
        if ($post['authorid'])
        {
            $uid .= ",".$post['authorid'];
        }
    }
    $query = $db->query("SELECT  m.uid, m.username, m.groupid, m.regdate, m.lastactivity, m.posts, m.digestposts, m.oltime,
                m.pageviews, m.credits, m.extcredits1, m.extcredits2, m.extcredits3, m.extcredits4, m.extcredits5, m.extcredits6,
                m.extcredits7, m.extcredits8, m.email, m.gender, m.showemail, m.invisible, m.avatarshowid, m.xspacestatus, mf.nickname, mf.site,
                mf.icq, mf.qq, mf.yahoo, mf.msn, mf.taobao, mf.alipay, mf.location, mf.medals, mf.avatar, mf.avatarwidth,
                mf.avatarheight, mf.sightml AS signature, mf.customstatus FROM {$tablepre}members m 
                LEFT JOIN {$tablepre}memberfields  mf ON mf.uid=m.uid
                WHERE m.uid IN ($uid)
                ");
}
$mtime = explode(‘ ‘, microtime());        
$runtime = ($mtime[1] + $mtime[0] – $discuz_starttime);
?>

运行时间依次为:
14.0723490715 14.4422261715 13.4820911884 13.289301157 13.0309917927 13.1161420345 12.8048489094 12.6428101063
运行时间大大缩短,基本在13秒左右

程序三:先读取相关cdb_posts中的数据,再分别查询cdb_members和cdb_memberfields中的信息。

query("SELECT * FROM {$tablepre}posts WHERE tid=’$i’ AND invisible=’0′ ORDER BY dateline LIMIT 60");
    while ($post = $db->fetch_array($query))
    {
        if ($post['authorid'])
        {
            $uid .= ",".$post['authorid'];
        }
    }
    $query = $db->query("SELECT  uid, username, groupid, regdate, lastactivity, posts, digestposts, oltime,
                pageviews, credits, extcredits1, extcredits2, extcredits3, extcredits4, extcredits5, extcredits6,
                extcredits7, extcredits8, email, gender, showemail, invisible, avatarshowid, xspacestatus FROM {$tablepre}members 
                
                WHERE uid IN ($uid)
                ");    
    $query = $db->query("SELECT  nickname, site,icq, qq, yahoo, msn, taobao, alipay, location, medals, avatar, avatarwidth,
                avatarheight, sightml AS signature, customstatus FROM {$tablepre}memberfields 
                
                WHERE uid IN ($uid)
                ");        
}
$mtime = explode(‘ ‘, microtime());        
$runtime = ($mtime[1] + $mtime[0] – $discuz_starttime);
?>

运行时间依次为:
14.2967050076 13.7778971195 14.3256859779 15.5803039074 13.5902359486 13.9162919521 14.1429729462 14.4423420429
基本在14秒左右

结论,对于数据量较大的网站,采用先读取相关cdb_posts中的数据,再用联表查询用户的信息的方式,可以更提高程序运行效率,减少对服务器的负载,虽然增加了一次查询,但是由于查询的语句简单化,因此反而可以节省一些运行时间。

*******************************
ps:以上方法我都做了测试,结果却跟上面的不一样,我测得的还是论坛原本的代码用时最少,倒是把leftjoin变为逗号直接连表查询会稍微快一些。