??xml version="1.0" encoding="utf-8" standalone="yes"?> SQL语句Q? SQL优化Q? ORACLE优化器: 1 帔R优化Q? 2 操作W优化: 其中Q? ~~ ANY和SOME 操作W优? ~~ ALL操作W优? ~~ BETWEEN 操作W优? ~~ NOT 操作W优? 如何~写高效的SQL: 1 合理的烦引设计: 语句B 语句C ȝ1 2 避免使用不兼容的数据cdQ? 3 IS NULL 与IS NOT NULLQ? 4 IN和EXISTSQ? 5 IN、OR子句怼使用工作表,使烦引失效: 6 避免或简化排序: 7 消除对大型表行数据的序存取Q? 8 避免相关子查询: 9 避免困难的正规表辑ּQ? 10 不充份的q接条gQ? 11 存储q程中,采用临时表优化查询: 好了Q搞定? 影响SQL server性能的关键三个方?转脓) 关键词:Sql Server 转脓?http://202.200.129.193/ 优化数据库和应用E序打下良好的基?/p>
标准化的数据库逻辑设计包括用多的、有怺关系的窄表来代替很多列的长数据表。下面是一些用标准化 表的一些好处?/p>
A:׃表窄Q因此可以排序和徏立烦引更?/p>
B:׃多表Q所以多镞的索引成ؓ可能 C:更窄更紧凑的索引 D:每个表中可以有少一些的索引Q因此可以提高insert update delete{的速度Q因些操作在索引 多的情况下会对系l性能产生很大的媄?/p>
E:更少的空值和更少的多余|增加了数据库的紧凑?/p>
׃标准化,所以会增加了在获取数据时引用表的数目和光的连接关pȝ复杂性。太多的表和复杂的连接关pM降低服务器的性能Q因此在q两者之间需要综合考虑? 2 索引的设? 5000 Nonclustered index 镞烦引和非镞索引的选择 <1:>镞烦引是行的物理序和烦引的序是一致的。页U,低层{烦引的各个U别上都包含实际的数据页。一个表只能是有一个镞索引。由于update,delete语句要求相对多一些的L作,因此镞烦引常常能加速这L操作。在臛_有一个烦引的表中Q你应该有一个镞索引? 当有大量的行正在被插入表中时Q要避免在本表一个自然增长(例如Qidentity列)的列上徏立镞索引。如果你建立了镞的烦引,那么insert的性能׃大大降低。因为每一个插入的行必d表的最后,表的最后一个数据页? <2:>一个非镞的索引是行的物理ơ序与烦引的ơ序是不同的。一个非镞烦引的叶包含了指向行数据늚指针? 3 查询语句的设?/p>
SQL Server优化器通过分析查询语句Q自动对查询q行优化q决定最有效的执行方案。优化器分析查询语句来决定那个子句可以被优化Qƈ针对可以被优化查询的子句来选择有用的烦引。最后优化器比较所有可能的执行Ҏq择最有效的一个方案出来?
FOR INSERT
AS
declare @num as int
declare @uid as int
select @num=cmoney,@uid=userid from [inserted]
update clubuser set score=score+@num/2 where id=@uid
FOR DELETE
AS
declare @num as int
declare @uid as int
select @num=cmoney,@uid=userid from [deleteed]
update clubuser set score=score-@num where id=@uid
FOR INSERT
AS
declare @num int
declare @uid int
select @num=score,@uid=userid from [inserted]
update clubuser set score=score+@num where id=@uid
Q这个表不存在删除)
FOR INSERT
AS
declare @num int
declare @uid int
declare @prid int
select @prid=prizeid,@uid=userid from [inserted]
select @num=Score from prize where id=@prid
update clubuser set score=score-@num where id=@uid
FOR Delete
AS
declare @num int
declare @uid int
declare @prid int
select @prid=prizeid,@uid=userid from [deleted]
if @@rowcount>0
begin
select @num=score from prize where id=@prid
update clubuser set score=score+@num where id=@uid
end
是对数据?数据)q行操作的惟一途径Q?
消耗了70%~90%的数据库资源Q独立于E序设计逻辑Q相对于对程序源代码的优化,对SQL语句的优化在旉成本和风险上的代价都很低Q?
可以有不同的写法Q易学,隄通?/p>
固定的SQL书写习惯Q相同的查询量保持相同Q存储过E的效率较高?
应该~写与其格式一致的语句Q包括字母的大小写、标点符受换行的位置{都要一?/p>
在Q何可能的时候都会对表达式进行评伎ͼq且把特定的语法l构转换成等Ll构Q这么做的原因是
要么l果表达式能够比源表辑ּh更快的速度
要么源表辑ּ只是l果表达式的一个等仯义结?
不同的SQLl构有时h同样的操作(例如Q? ANY (subquery) and IN (subquery)Q,ORACLE会把他们映射C个单一的语义结构?/p>
帔R的计是在语句被优化时一ơ性完成,而不是在每次执行时。下面是索月薪大?000的的表达式:
sal > 24000/12
sal > 2000
sal*12 > 24000
如果SQL语句包括W一U情况,优化器会单地把它转变成第二种?
优化器不会简化跨比较符的表辑ּQ例如第三条语句Q鉴于此Q应量写用帔R跟字D|较检索的表达式,而不要将字段|于表达式当中。否则没有办法优化,比如如果sal上有索引Q第一和第二就可以使用Q第三就难以使用?/p>
优化器把使用LIKE操作W和一个没有通配W的表达式组成的索表辑ּ转换Z个?”操作符表达式?
例如Q优化器会把表达式ename LIKE 'SMITH'转换为ename = 'SMITH'
优化器只能{换涉及到可变长数据类型的表达式,前一个例子中Q如果ENAME字段的类型是CHAR(10)Q?那么优化器将不做M转换?
一般来讲LIKE比较难以优化?/p>
~~ IN 操作W优化:
优化器把使用IN比较W的索表辑ּ替换为等L使用?”和“OR”操作符的检索表辑ּ?
例如Q优化器会把表达式ename IN ('SMITH','KING','JONES')替换?
ename = 'SMITH' OR ename = 'KING' OR ename = 'JONES?/p>
优化器将跟随值列表的ANY和SOME索条件用{h的同{操作符和“OR”组成的表达式替换?
例如Q优化器如下所C的W一条语句用W二条语句替换:
sal > ANY (:first_sal, :second_sal)
sal > :first_sal OR sal > :second_sal
优化器将跟随子查询的ANY和SOME索条件{换成由“EXISTS”和一个相应的子查询组成的索表辑ּ?
例如Q优化器如下所C的W一条语句用W二条语句替换:
x > ANY (SELECT sal FROM emp WHERE job = 'ANALYST')
EXISTS (SELECT sal FROM emp WHERE job = 'ANALYST' AND x > sal)
优化器将跟随值列表的ALL操作W用{h的?”和“AND”组成的表达式替换。例如:
sal > ALL (:first_sal, :second_sal)表达式会被替换ؓQ?
sal > :first_sal AND sal > :second_sal
对于跟随子查询的ALL表达式,优化器用ANY和另外一个合适的比较W组成的表达式替换。例?
x > ALL (SELECT sal FROM emp WHERE deptno = 10) 替换为:
NOT (x <= ANY (SELECT sal FROM emp WHERE deptno = 10))
接下来优化器会把W二个表辑ּ适用ANY表达式的转换规则转换Z面的表达式:
NOT EXISTS (SELECT sal FROM emp WHERE deptno = 10 AND x <= sal)
优化器L用?gt;=”和?lt;=”比较符来等L代替BETWEEN操作W?
例如Q优化器会把表达式sal BETWEEN 2000 AND 3000用sal >= 2000 AND sal <= 3000来代ѝ?/p>
优化器L试图化检索条件以消除“NOT”逻辑操作W的影响Q这涉及到“NOT”操作符的消除以及代以相应的比较q算W?
例如Q优化器下面的W一条语句用W二条语句代替:
NOT deptno = (SELECT deptno FROM emp WHERE ename = 'TAYLOR')
deptno <> (SELECT deptno FROM emp WHERE ename = 'TAYLOR')
通常情况下一个含有NOT操作W的语句有很多不同的写法Q优化器的{换原则是低쀜NOT”操作符后边的子句尽可能的简单,即可能会ɾl果表达式包含了更多的“NOT”操作符?
例如Q优化器如下所C的W一条语句用W二条语句代替:
NOT (sal < 1000 OR comm IS NULL)
NOT sal < 1000 AND comm IS NOT NULL sal >= 1000 AND comm IS NOT NULL
当然要考虑sql帔R的优化和操作W的优化啦,另外Q还需要:
例:表record?20000行,试看在不同的索引下,下面几个SQL的运行情况:
语句A
SELECT count(*) FROM record
WHERE date >'19991201' and date < '19991214?and amount >2000
SELECT count(*) FROM record
WHERE date >'19990901' and place IN ('BJ','SH')
SELECT date,sum(amount) FROM record
group by date
1 在date上徏有一个非聚集索引
AQ?25U?
BQ?27U?
CQ?55U?
分析Q?
date上有大量的重复|在非聚集索引下,数据在物理上随机存放在数据页上,在范围查找时Q必L行一ơ表扫描才能扑ֈq一范围内的全部行?
2 在date上的一个聚集烦?
AQ(14U)
BQ(14U)
CQ(28U)
分析Q?
在聚集烦引下Q数据在物理上按序在数据页上,重复g排列在一P因而在范围查找Ӟ可以先找到这个范围的h点,且只在这个范围内扫描数据,避免了大范围扫描Q提高了查询速度?
3 在placeQdateQamount上的l合索引
AQ(26U)
CQ(27U)
BQ(< 1U)
分析Q?
q是一个不很合理的l合索引Q因为它的前导列是placeQ第一和第二条SQL没有引用placeQ因此也没有利用上烦引;W三个SQL使用了placeQ且引用的所有列都包含在l合索引中,形成了烦引覆盖,所以它的速度是非常快的?
4 在dateQplaceQamount上的l合索引
AQ?(< 1U?
BQ(< 1U)
CQ(11U)
分析Q?
q是一个合理的l合索引。它date作ؓ前导列,使每个SQL都可以利用烦引,q且在第一和第三个SQL中Ş成了索引覆盖Q因而性能辑ֈ了最优?/p>
~省情况下徏立的索引是非聚集索引Q但有时它ƈ不是最佳的Q合理的索引设计要徏立在对各U查询的分析和预上。一般来_
有大量重复倹{且l常有范围查询(between, >,< Q?gt;=,< =Q和order by、group by发生的列Q考虑建立聚集索引Q?
l?常同时存取多列,且每列都含有重复值可考虑建立l合索引Q在条g表达式中l常用到的不同D多的列上建立索,在不同值少的列上不要徏立烦引。比如在雇员 表的“性别”列上只有“男”与“女”两个不同|因此无必要建立索引。如果徏立烦引不但不会提高查询效率,反而会严重降低更新速度?
l合索引要尽量关键查询形成索引覆盖Q其前导列一定是使用最频繁的列?/p>
例如float和INt、char和varchar、bINary和varbINary是不兼容的。数据类型的不兼容可能优化器无法执行一些本来可以进行的优化操作。例?
SELECT name FROM employee WHERE salary Q?60000
在这条语句中,如salary字段是money型的,则优化器很难对其q行优化,因ؓ60000是个整型数。我们应当在~程时将整型转化成ؓ钱币?而不要等到运行时转化?/p>
?能用null作烦引,M包含null值的列都不会被包含在烦引中。即使烦引有多列q样的情况下Q只要这些列中有一列含有nullQ该列就会从索引中排 除。也是说如果某列存在空|即对该列徏索引也不会提高性能。Q何在WHERE子句中用is null或is not null的语句优化器是不?怋用烦引的?/p>
EXISTS要远比IN的效率高。里面关pdfull table scan和range scan。几乎将所有的IN操作W子查询改写Z用EXISTS的子查询?
例子Q?
语句1
SELECT dname, deptno FROM dept
WHERE deptno NOT IN
(SELECT deptno FROM emp);
语句2
SELECT dname, deptno FROM dept
WHERE NOT EXISTS
(SELECT deptno FROM emp
WHERE dept.deptno = emp.deptno);
明显的,2要比1的执行性能好很?
因ؓ1中对empq行了full table scan,q是很浪Ҏ间的操作。而且1中没有用到emp的INdexQ?
因ؓ没有WHERE子句。?中的语句对empq行的是range scan?/p>
如果不生大量重复|可以考虑把子句拆开。拆开的子句中应该包含索引?/p>
应当化或避免对大型表q行重复的排序。当能够利用索引自动以适当的次序生输出时Q优化器避免了排序的步骤。以下是一些媄响因素:
索引中不包括一个或几个待排序的列;
group by或order by子句中列的次序与索引的次序不一P
排序的列来自不同的表?
Z避免不必要的排序Q就要正地增徏索引Q合理地合ƈ数据库表Q尽有时可能媄响表的规范化Q但相对于效率的提高是值得的)。如果排序不可避免,那么应当试图化它Q如~小排序的列的范围等?/p>
?嵌套查询中,对表的顺序存取对查询效率可能产生致命的媄响。比如采用顺序存取策略,一个嵌?层的查询Q如果每层都查询1000行,那么q个查询p查询 10亿行数据。避免这U情늚主要Ҏ是对连接的列进行烦引。例如,两个表:学生表(学号、姓名、年??Q和选课表(学号、课E号、成l)。如果两?表要做连接,p在“学号”这个连接字D上建立索引?
q可以用ƈ集来避免序存取。尽在所有的查列上都有烦引,但某些Ş式的WHERE子句优化器用顺序存取。下面的查询强q对orders表执行顺序操作:
SELECT Q?FROM orders WHERE (customer_num=104 AND order_num>1001) OR order_num=1008
虽然在customer_num和order_num上徏有烦引,但是在上面的语句中优化器q是使用序存取路径扫描整个表。因个语句要索的是分ȝ行的集合Q所以应该改为如下语句:
SELECT Q?FROM orders WHERE customer_num=104 AND order_num>1001
UNION
SELECT Q?FROM orders WHERE order_num=1008
q样p利用索引路径处理查询?/p>
一个列的标{时在L询和WHERE子句中的查询中出玎ͼ那么很可能当L询中的列值改变之后,子查询必重新查询一ơ。查询嵌套层ơ越多,效率低Q因此应当尽量避免子查询。如果子查询不可避免Q那么要在子查询中过滤掉可能多的行?/p>
MATCHES和LIKE关键字支持通配W匹配,技术上叫正规表辑ּ。但q种匚w特别耗费旉。例如:SELECT Q?FROM customer WHERE zipcode LIKE ?8_ _ _?
即在zipcode字段上徏立了索引Q在q种情况下也q是采用序扫描的方式。如果把语句改ؓSELECT Q?FROM customer WHERE zipcode >?8000”,在执行查询时׃利用索引来查询,昄会大大提高速度?
另外Q还要避免非开始的子串。例如语句:SELECT Q?FROM customer WHERE zipcode[2Q?] >?0”,在WHERE子句中采用了非开始子Ԍ因而这个语句也不会使用索引?/p>
例:表card?896行,在card_no上有一个非聚集索引Q表account?91122行,在account_no上有一个非聚集索引Q试看在不同的表q接条g下,两个SQL的执行情况:
SELECT sum(a.amount) FROM account a,card b WHERE a.card_no = b.card_no
Q?0U)
SQL改ؓQ?
SELECT sum(a.amount) FROM account a,card b WHERE a.card_no = b.card_no and a.account_no=b.account_no
Q?lt; 1U)
分析Q?
在第一个连接条件下Q最x询方案是account作外层表Qcard作内层表Q利用card上的索引Q其I/Oơ数可由以下公式估算为:
外层表account上的22541?Q外层表account?91122?内层表card上对应外层表W一行所要查扄3)=595907ơI/O
在第二个q接条g下,最x询方案是card作外层表Qaccount作内层表Q利用account上的索引Q其I/Oơ数可由以下公式估算为:
外层表card上的1944?Q外层表card?896?内层表account上对应外层表每一行所要查扄4)= 33528ơI/O
可见Q只有充份的q接条gQ真正的最x案才会被执行?
多表操作在被实际执行前,查询优化器会Ҏq接条gQ列出几l可能的q接Ҏq从中找出系l开销最的最x案。连接条件要充䆾考虑带有索引的表、行数多的表Q内外表的选择可由公式Q外层表中的匚w行数*内层表中每一ơ查扄ơ数定Q乘U最ؓ最x案?
不可优化的WHERE子句
?
下列SQL条g语句中的列都建有恰当的烦引,但执行速度却非常慢Q?
SELECT * FROM record WHERE substrINg(card_no,1,4)='5378'
(13U?
SELECT * FROM record WHERE amount/30< 1000
Q?1U)
SELECT * FROM record WHERE convert(char(10),date,112)='19991201'
Q?0U)
分析Q?
WHERE子句中对列的M操作l果都是在SQLq行旉列计算得到的,因此它不得不q行表搜索,而没有用该列上面的索引Q如果这些结果在查询~译时就能得刎ͼ那么可以被SQL优化器优化,使用索引Q避免表搜烦Q因此将SQL重写成下面这P
SELECT * FROM record WHERE card_no like '5378%'
Q?lt; 1U)
SELECT * FROM record WHERE amount< 1000*30
Q?lt; 1U)
SELECT * FROM record WHERE date= '1999/12/01'
Q?lt; 1U)
?
1Q从parven表中按vendor_num的次序读数据Q?
SELECT part_numQvendor_numQprice FROM parven ORDER BY vendor_num
INTO temp pv_by_vn
q个语句序读parvenQ?0)Q写一个时表Q?0)Qƈ排序。假定排序的开销?00,d?00c?
2Q把临时表和vendor表连接,把结果输出到一个时表Qƈ按part_num排序Q?
SELECT pv_by_vnQ* vendor.vendor_num FROM pv_by_vnQvendor
WHERE pv_by_vn.vendor_num=vendor.vendor_num
ORDER BY pv_by_vn.part_num
INTO TMP pvvn_by_pn
DROP TABLE pv_by_vn
q?个查询读取pv_by_vn(50?Q它通过索引存取vendor?.5万次Q但׃按vendor_numơ序排列Q实际上只是通过索引序地读 vendor表(40Q?=42)Q输出的表每늺95行,?60c写q存取这些页引发5Q?60=800ơ的dQ烦引共d892c?
3Q把输出和partq接得到最后的l果Q?
SELECT pvvn_by_pn.Q,part.part_desc FROM pvvn_by_pnQpart
WHERE pvvn_by_pn.part_num=part.part_num
DROP TABLE pvvn_by_pn
q样Q查询顺序地读pvvn_by_pn(160?Q通过索引读part?.5万次Q由于徏有烦引,所以实际上q行1772ơ磁盘读写,优化比例?0??/p>
其实sql的优化,各种数据库之间都是互通的
1 逻辑数据库和表的设计
数据库的逻辑设计、包括表与表之间的关pL优化关系型数据库性能的核心。一个好的逻辑数据库设计可以ؓ
定义h相关关系的主键和外来键时应该注意的事主要是Q用于连接多表的主键和参考的键要有相同的数据cd?/p>
A:量避免表扫?
查你的查询语句的where子句Q因是优化器重要x的地斏V包含在where里面的每一列(column)都是可能的侯选烦引,辑ֈ最优的性能Q考虑在下面给出的例子Q对于在where子句中给Zcolumn1q个列?
下面的两个条件可以提高烦引的优化查询性能Q?
W一Q在表中的column1列上有一个单索引
W二Q在表中有多索引Q但是column1是第一个烦引的?
避免定义多烦引而column1是第二个或后面的索引Q这L索引不能优化服务器性能
例如Q下面的例子用了pubs数据库?
SELECT au_id, au_lname, au_fname FROM authors
WHERE au_lname = 'White'
按下面几个列上徏立的索引会是对优化器有用的索引
?au_lname
?au_lname, au_fname
而在下面几个列上建立的烦引将不会对优化器起到好的作用
?au_address
?au_fname, au_lname
考虑使用H的索引在一个或两个列上Q窄索引比多索引和复合烦引更能有效。用H的索引Q在每一上
会有更多的行和更少的烦引别(相对与多索引和复合烦引而言Q,q将推进pȝ性能?
对于多列索引QSQL Serverl持一个在所有列的烦引上的密度统计(用于联合Q和在第一个烦引上?
histogramQ柱状图Q统计。根据统计结果,如果在复合烦引上的第一个烦引很被选择使用Q那么优化器对很多查询请求将不会使用索引?
有用的烦引会提高select语句的性能Q包括insert,uodate,delete?
但是Q由于改变一个表的内容,会影响索引。每一个insert,update,delete语句会使性能下降一些。实验表明,不要在一个单表上用大量的索引Q不要在׃n的列上(指在多表中用了参考约束)使用重叠的烦引?
在某一列上查唯一的数据的个数Q比较它与表中数据的行数做一个比较。这是数据的选择性,q比较结果将会帮助你军_是否某一列作Z选的索引列,如果需要,建哪一U烦引。你可以用下面的查询语句q回某一列的不同值的数目?
select count(distinct cloumn_name) from table_name
假设column_name是一?0000行的表,则看column_nameq回值来军_是否应该使用Q及应该使用什么烦引?
Unique values Index
20 Clustered index
3 No index
在下面的几个情况下,你可以考虑用镞索引Q?
例如Q?某列包括的不同值的个数是有限的Q但是不是极的Q?
֮表的州名列有50个左右的不同州名的羃写|可以使用镞烦引?
例如Q?对返回一定范围内值的列可以用镞索引Q比如用between,>,>=,<,<={等来对列进行操作的列上?
select * from sales where ord_date between '5/1/93' and '6/1/93'
例如Q?Ҏ询时q回大量l果的列可以使用镞烦引?
SELECT * FROM phonebook WHERE last_name = 'Smith'
当一个数据正在被插入Q这时这个数据页是被锁定的)Q所有的其他插入行必ȝ待直到当前的插入已经l束?
一个烦引的叶中包括实际的数据页Qƈ且在盘上的数据늚ơ序是跟镞烦引的逻辑ơ序一L?/p>
在一个表中可以有多个非镞索引Q你可以在以下几个情况下考虑使用非镞索引?
在有很多不同值的列上可以考虑使用非镞索引
例如Q一个part_id列在一个part表中
select * from employee where emp_id = 'pcm9809f'
查询语句中用order by 子句的列上可以考虑使用镞烦?/p>
在执行一个查询时Q用一个where子句来限制必d理的行数Q除非完全需要,否则应该避免在一个表中无限制地读q处理所有的行?
例如下面的例子,
select qty from sales where stor_id=7131
是很有效的比下面q个无限制的查询
select qty from sales
避免l客L最后数据选择q回大量的结果集。允许SQL Serverq行满它目的的函数限制l果集的大小是更有效的?
q能减少|络I/Oq能提高多用L相关q发时的应用E序性能。因Z化器x的焦点就是where子句的查询,以利用有用的索引。在表中的每一个烦引都可能成ؓ包括在where子句中的侯选烦引。ؓ了最好的性能可以늅下面的用于一个给定列column1的烦引?
W一Q在表中的column1列上有一个单索引
W二Q在表中有多索引Q但是column1是第一个烦引的列不要在where子句中用没有column1列烦引的查询语句Qƈ避免在where子句用一个多索引的非W一个烦引的索引?
q时多烦引是没有用的?
For example, given a multicolumn index on the au_lname, au_fname columns of the authors table in
the pubs database,
下面q个query语句利用了au_lname上的索引
SELECT au_id, au_lname, au_fname FROM authors
WHERE au_lname = 'White'
AND au_fname = 'Johnson'
SELECT au_id, au_lname, au_fname FROM authors
WHERE au_lname = 'White'
下面q个查询没有利用索引Q因Z使用了多索引的非W一个烦引的索引
SELECT au_id, au_lname, au_fname FROM authors
WHERE au_fname = 'Johnson'
CREATE TABLE Company_Info
(
id smallint IDENTITY(1,1) ,
username varchar(50) null,
password varchar(50) null,
PRIMARY KEY(id)
)
思\
------------昄哪些人相同,相同的数量是多少Q?/p>
select convert(int,SQRT(count(*))) as countU ,a.username from Company_Info a left join Company_Info b on
a.username=b.username and a.password=b.password
group by a.username having SQRT(count(*)) >1
----------取出所有相同的记录C个表MyRepeat
select c.* into MyRepeat from Company_Info c where c.username in(
select a.username from Company_Info a left join Company_Info b on
a.username=b.username and a.password=b.password
group by a.username having SQRT(count(*)) >1)
-----------在表MyRepeat中找出每个相同记录的除最大id之外
select a.id from MyRepeat a where id not in(select max(b.id) from MyRepeat b group by b.username)--得出所有需要删除的id
-----------
最后得?br />
delete Company_Info where id in (select h.id from (select c.* from Company_Info c where c.username in(select a.username from Company_Info a left join Company_Info b on a.username=b.username and a.password=b.password group by a.username having SQRT(count(*)) >1) ) h where h.id not in( select max(l.id) from (select k.id,username from (select f.* from Company_Info f where f.username in(select g.username from Company_Info g left join Company_Info o on g.username=o.username and g.password=o.password group by g.username having SQRT(count(*)) >1)) k ) l group by l.username))