package Ġio . ze ko . db . sql Ċ Ċ import Ġio . ze ko . db . sql . aggreg ations .* Ċ import Ġio . ze ko . db . sql . dsl .* Ċ import Ġio . ze ko . db . sql . operators . isNotNull Ċ import Ġorg . spe k framework . spe k 2 . Spe k Ċ import Ġorg . spe k framework . spe k 2 . style . specification . describe Ċ import Ġkotlin . test . assertEquals Ċ Ċ class ĠMySQL Join Query Spec Ġ: ĠSpe k ({ ĊĊĠĠĠ Ġfun Ġdebug ( msg : ĠAny ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( false ) Ġprintln ( msg . toString ()) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġdescribe (" Query ĠBuilder ĠDSL ĠJoin ĠQueries ĠMySQL Ġtest ") Ġ{ ĊĠĠĠĠĠĠĠ Ġcontext (" Given Ġmultiple Ġtables Ġjoin ( user Ġhas Ġaddress , Ġand Ġhas Ġmany Ġroles )") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit (" should Ġmatch Ġsql Ġwith Ġone Ġtable Ġleft Ġjoin ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsql Ġ= ĠQuery (). fields ("* ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. from (" user ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. leftJoin (" address "). on (" user _ id Ġ= Ġuser . id ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. to Sql () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdebug ( sql ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals (" SELECT Ġ* ĠFROM Ġuser ĠLEFT ĠJOIN Ġaddress ĠON Ġ( address . user _ id Ġ= Ġuser . id Ġ) ", Ġsql ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġit (" should Ġmatch Ġsql Ġwith Ġone Ġtable Ġinner Ġjoin Ġwith Ġfield Ġrename ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsql Ġ= ĠQuery (). fields (" user . id ĠAS Ġuser _ id ", Ġ" name ", Ġ" street 1 ", Ġ" street 2 ", Ġ" address . id ĠAS Ġaddress _ id ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. from (" user ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. inner Join (" address "). on (" user _ id Ġ= Ġuser . id ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. to Sql () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdebug ( sql ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals (" SELECT Ġuser . id ĠAS Ġuser _ id , Ġname , Ġstreet 1 , Ġstreet 2 , Ġaddress . id ĠAS Ġaddress _ id ĠFROM Ġuser ĠINNER ĠJOIN Ġaddress ĠON Ġ( address . user _ id Ġ= Ġuser . id Ġ) ", Ġsql ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġit (" should Ġmatch Ġsql Ġwith Ġone Ġtable Ġleft Ġjoin Ġwith Ġfield Ġselection Ġand Ġwhere Ġconditions ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsql Ġ= ĠQuery () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. table (" user "). fields (" id ", Ġ" name ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. table (" address "). fields (" id ", Ġ" street 1 ", Ġ" street 2 ", Ġ" user . id Ġ= Ġuser _ id ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. from (" user ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. leftJoin (" address "). on (" user _ id Ġ= Ġuser . id ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. where ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" user . status " Ġgreater Ġ 0 Ġor ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis NotNull (" user . id ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. order Desc (" user . name ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. to Sql () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdebug ( sql ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals (" SELECT Ġuser . id Ġas Ġ` user - id `, Ġuser . name Ġas Ġ` user - name `, Ġaddress . id Ġas Ġ` address - id `, Ġaddress . street 1 Ġas Ġ` address - street 1 `, Ġaddress . street 2 Ġas Ġ` address - street 2 `, Ġuser . id Ġas Ġ` address - user _ id ` ĠFROM Ġuser ĠLEFT ĠJOIN Ġaddress ĠON Ġ( address . user _ id Ġ= Ġuser . id Ġ) ĠWHERE Ġuser . status Ġ> Ġ 0 ĠOR Ġuser . id ĠIS ĠNOT ĠNULL ĠORDER ĠBY Ġuser . name ĠDESC ", Ġsql ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġit (" should Ġmatch Ġsql Ġwith Ġthree Ġtable Ġjoins ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsql Ġ= ĠQuery () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. table (" user "). fields (" id ", Ġ" name ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. table (" role "). fields (" id ", Ġ" role _ name ", Ġ" user . id Ġ= Ġuser _ id ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. table (" address "). fields (" id ", Ġ" street 1 ", Ġ" street 2 ", Ġ" user . id Ġ= Ġuser _ id ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. from (" user ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. leftJoin (" address "). on (" user _ id Ġ= Ġuser . id ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. leftJoin (" user _ has _ role "). on (" user _ id Ġ= Ġuser . id ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. leftJoin (" role "). on (" id Ġ= Ġuser _ has _ role . role _ id ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. where ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" user . status " Ġgreater Ġ 0 Ġor ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ(" user . id " Ġnot In List ĠarrayOf ( 1 , Ġ 2 , Ġ 3 )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. order (" user . id ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. to Sql () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdebug ( sql ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals (" SELECT Ġuser . id Ġas Ġ` user - id `, Ġuser . name Ġas Ġ` user - name `, Ġrole . id Ġas Ġ` role - id `, Ġrole . role _ name Ġas Ġ` role - role _ name `, Ġuser . id Ġas Ġ` role - user _ id `, Ġaddress . id Ġas Ġ` address - id `, Ġaddress . street 1 Ġas Ġ` address - street 1 `, Ġaddress . street 2 Ġas Ġ` address - street 2 `, Ġuser . id Ġas Ġ` address - user _ id ` ĠFROM Ġuser ĠLEFT ĠJOIN Ġaddress ĠON Ġ( address . user _ id Ġ= Ġuser . id Ġ) ĠLEFT ĠJOIN Ġuser _ has _ role ĠON Ġ( user _ has _ role . user _ id Ġ= Ġuser . id Ġ) ĠLEFT ĠJOIN Ġrole ĠON Ġ( role . id Ġ= Ġuser _ has _ role . role _ id Ġ) ĠWHERE Ġuser . status Ġ> Ġ 0 ĠOR Ġuser . id ĠNOT ĠIN Ġ( 1 , 2 , 3 ) ĠORDER ĠBY Ġuser . id ĠASC ", Ġsql ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġit (" should Ġmatch Ġsql Ġwith Ġthree Ġtable Ġjoins Ġwith Ġselect Ġfrom Ġsub query ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsql Ġ= ĠQuery () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. table (" user "). fields (" id ", Ġ" name ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. table (" role "). fields (" id ", Ġ" role _ name ", Ġ" user . id Ġ= Ġuser _ id ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. table (" address "). fields (" id ", Ġ" street 1 ", Ġ" street 2 ", Ġ" user . id Ġ= Ġuser _ id ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. from ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠQuery (). fields ("* "). from (" user ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. where (" id " Ġless Eq Ġ 1 0 0 Ġand Ġ(" age " Ġgreater Ġ 5 0 )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. order (" user . id ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. limit ( 1 0 , Ġ 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. as Table (" user ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. leftJoin (" address "). on (" user _ id Ġ= Ġuser . id ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. leftJoin (" user _ has _ role "). on (" user _ id Ġ= Ġuser . id ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. leftJoin (" role "). on (" id Ġ= Ġuser _ has _ role . role _ id ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. where ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" user . status " Ġgreater Ġ 0 Ġor ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ(" user . id " Ġnot In List ĠarrayOf ( 1 , Ġ 2 , Ġ 3 )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. order (" user . name ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. to Sql () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdebug ( sql ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals (" SELECT Ġuser . id Ġas Ġ` user - id `, Ġuser . name Ġas Ġ` user - name `, Ġrole . id Ġas Ġ` role - id `, Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" role . role _ name Ġas Ġ` role - role _ name `, Ġuser . id Ġas Ġ` role - user _ id `, Ġaddress . id Ġas Ġ` address - id `, Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" address . street 1 Ġas Ġ` address - street 1 `, Ġaddress . street 2 Ġas Ġ` address - street 2 `, Ġuser . id Ġas Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"` address - user _ id ` ĠFROM Ġ( SELECT Ġ* ĠFROM Ġuser ĠWHERE Ġid Ġ<= Ġ 1 0 0 ĠAND Ġage Ġ> Ġ 5 0 Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" ORDER ĠBY Ġuser . id ĠASC ĠLIMIT Ġ 1 0 ĠOFFSET Ġ 0 ) ĠAS Ġuser ĠLEFT ĠJOIN Ġaddress ĠON Ġ( address . user _ id Ġ= Ġuser . id Ġ) Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" LEFT ĠJOIN Ġuser _ has _ role ĠON Ġ( user _ has _ role . user _ id Ġ= Ġuser . id Ġ) Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" LEFT ĠJOIN Ġrole ĠON Ġ( role . id Ġ= Ġuser _ has _ role . role _ id Ġ) Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" WHERE Ġuser . status Ġ> Ġ 0 ĠOR Ġuser . id ĠNOT ĠIN Ġ( 1 , 2 , 3 ) Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" ORDER ĠBY Ġuser . name ĠASC ", Ġsql ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġit (" should Ġmatch Ġsql Ġwith Ġthree Ġtable Ġjoins Ġwith Ġgroup Ġby Ġand Ġhaving ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsql Ġ= ĠQuery () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. table (" user "). fields (" id ", Ġ" name ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. table (" role "). fields (" id ", Ġ" role _ name ", Ġ" user . id Ġ= Ġuser _ id ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. table (" address "). fields (" id ", Ġ" street 1 ", Ġ" street 2 ", Ġ" user . id Ġ= Ġuser _ id ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. from (" user ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. leftJoin (" address "). on (" user _ id Ġ= Ġuser . id ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. leftJoin (" user _ has _ role "). on (" user _ id Ġ= Ġuser . id ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. leftJoin (" role "). on (" id Ġ= Ġuser _ has _ role . role _ id ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. where ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" user . status " Ġgreater Ġ 0 Ġor ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ(" user . id " Ġnot In List ĠarrayOf ( 1 , Ġ 2 , Ġ 3 )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. groupBy (" role . id ", Ġ" role . name ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. having ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsum Gt (" role . id ", Ġ 2 ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcount (" role . id ") Ġless Ġ 1 0 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. order (" user . id ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. limit ( 1 0 , Ġ 2 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. to Sql () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdebug ( sql ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠassertEquals (" SELECT Ġuser . id Ġas Ġ` user - id `, Ġuser . name Ġas Ġ` user - name `, Ġrole . id Ġas Ġ` role - id `, Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" role . role _ name Ġas Ġ` role - role _ name `, Ġuser . id Ġas Ġ` role - user _ id `, Ġaddress . id Ġas Ġ` address - id `, Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" address . street 1 Ġas Ġ` address - street 1 `, Ġaddress . street 2 Ġas Ġ` address - street 2 `, Ġuser . id Ġas Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"` address - user _ id ` ĠFROM Ġuser ĠLEFT ĠJOIN Ġaddress ĠON Ġ( address . user _ id Ġ= Ġuser . id Ġ) Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" LEFT ĠJOIN Ġuser _ has _ role ĠON Ġ( user _ has _ role . user _ id Ġ= Ġuser . id Ġ) Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" LEFT ĠJOIN Ġrole ĠON Ġ( role . id Ġ= Ġuser _ has _ role . role _ id Ġ) Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" WHERE Ġuser . status Ġ> Ġ 0 ĠOR Ġuser . id ĠNOT ĠIN Ġ( 1 , 2 , 3 ) Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" GROUP ĠBY Ġrole . id , Ġrole . name Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" HAV ING ĠSUM ( Ġrole . id Ġ) Ġ> Ġ 2 ĠAND ĠCOUNT ( Ġrole . id Ġ) Ġ< Ġ 1 0 ĠORDER ĠBY Ġuser . id ĠASC ĠLIMIT Ġ 1 0 ĠOFFSET Ġ 2 0 ", Ġsql ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ }) Ċ