Download as pdf or txt
Download as pdf or txt
You are on page 1of 11

(http://www.masterzendframework.

com/)

?=HQG?'E?6TO&UHDWLQJ-RLQVDQG8QLRQV
ZLWK(DV
In the first part of this series on \Zend\Db\Sql\Select, we jumped the gun a bit and went
straight in to looking at building Where clauses. We looked at a number of the predicates
that are available to us, such as In, Between and EqualTo and saw just how easy
\Zend\Db\Sql\Select makes both building and maintaining queries.

In this, the second part, were backtracking a bit and looking at Joins and a slightly more
esoteric feature of SQL UNIONs. By the end of todays tutorial, youll be building some
pretty good queries that should satisfy most of your daily requirements.

-RLQV
Selecting information from one tables fine. But you quickly need to select across a
number of tables. Most queries I see in code that Ive taken on in consulting projects and
other roles normally involves at least one join (even if its a self-join at times).

If youd like a good (visual) refresher on SQL joins, read this post from Jeff Atwood
(http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html) over at
Coding Horror.

An interesting point Ive heard, circumstantially, is that after a number of joins, the
performance of the query begins to break down because most RDBMSs are not
optimized for more than that. However I dont have a link supporting that. But this quote
from AskTom at Oracle (http://asktom.oracle.com/pls/asktom/f?
p=100:11:0::::P11_QUESTION_ID:6788612863167) sums it up well:

A 20 table join no worries, well, except that I cannot imagine the data
model that would make me do that!)

However the physical limits are:

MySQL (http://dev.mysql.com/doc/refman/5.0/en/joins-limits.html): 61
MSSQL Server (http://dba.stackexchange.com/questions/125/whats-the-maximum-numberof-tables-that-can-be-referenced-in-a-query-in-mysql): 256
Oracle (http://asktom.oracle.com/pls/asktom/f?
p=100:11:0::::P11_QUESTION_ID:6788612863167) Not known, but stated as easily over 300

With that said, lets build on the previous tutorial in this series and go through building
joins, including Inner, Left, Right and Outer (well include a bonus a self join).

Below is the schema of the additional table well use to demonstrate the joins. Its a
simple department table. Were going to construct queries that show things such as: who

is the manager of department X and what department is which user in.

'HSDUWPHQW7DEOH

 

  
  


 

 



,QQHU-RLQ
Lets start with a simple join and create a query to find out which users are in which
department. Well create a query which starts with tbluser and joins on to tbldepartment
based on the UserID column. The query will be as follows:



    

To construct this query, well use the following code:


  
 

Here, weve first created a new Select object whose base table is tbluser. Then, weve
called the join function on it, passing in an array, because we want tbldepartment to be
aliased to d. Then, weve specified the join condition as the second argument. Finally,
weve used the order function to specify the sort order of the records.

/HIW-RLQ
Now, what if not all users were yet assigned to a department? In that case, we could
slightly change the query to perform a left join. If youre not familiar, a left join returns all
records from the table in the left side of the equation, even if they have no matching
records in the one on the right.

Our query will change slightly, as follows:



     

To construct this query, well use the previous code, :




  

   
 

Here, weve passed in two extra arguments to the join function, columns and type. For
columns, weve used the SQL_STAR constant, as we want all the columns. For type,
weve used the JOIN_LEFT constant, which will result in a left join.

5LJKW-RLQ
Now, what if not all departments which were yet assigned to a user? In that case, we
could slightly change the query, again, to perform a right join. Right joins are the inverse
of left joins; returning all records in the right hand table of the equation, which may or may
not have a matching record in the table on the left.

Our query will change slightly, as follows:



     

To construct this query, well use the previous code, :




  

  

 


Here, weve only made one change, the type constant, to JOIN_RIGHT.

2XWHU-RLQ
Now what if we want all records in both tables in the join, irrespective of whether they
have a counterpart record? In that case, wed construct an outer join. Yet again our query
will change slightly, as follows:



    

To construct this query, well use the previous code, :




  

  
 

Here, weve again changed the type constant, to JOIN_OUTER.

6HOI-RLQ
This is one that I find really interesting, joining a table on itself. In this case, the query
doesnt really get too complex, but just takes a bit more work and possibly a bit more
time to understand.

What were wanting to do is the original inner join, so well have the users linked with
departments. Then, we want to link the users on the departments again, but this time,
well be using the ManagerID in tbldepartment as the user identifying.



    
    

To construct this query, well use the following code:



  


  

 

To perform the self join, weve added another call to join, specifying the join table as
tbluser, but this time with a different alias and joining on ManagerID as weve said
previously.

/LPLWLQJ&ROXPQVLQWKH'DWDVHW
In all of these examples, we could have limited the columns in the dataset returned. And,
if this were a live application, Id expect that this would happen. Returning .* is ok if the
table has only a few columns.

But how often do tables remain small? How regularly are these types of queries forgotten,
resulting in an application whose performance seems to mysteriously degrade over time.

So, to limit the columns returned in the joined table, replace Select::SQL_STAR in the
examples above with an array. This can be a combination of either just the names of the
columns to be returned, or an associative array where the key is the alias and the value is
the column name.

8QLRQV,QWHUVHFWVDQG([FHSWV

In the comments from the previous tutorial on Select, X asked about Union queries and
how they are made. If youre not familiar with a Union query, the Wikipedia entry
(http://en.wikipedia.org/wiki/Set_operations_%28SQL%29) describes one as:

In SQL the UNION clause combines the results of two SQL queries into a
single table of all matching rows. The two queries must result in the same
number of columns and compatible data types in order to unite. Any
duplicate records are automatically removed unless UNION ALL is used.

To the best of my knowledge, there is no specific UNION function in the Select classes.
Nor does there need to be. When we consider that a Union is only two or more queries
combined with the keyword UNION, it would be pretty pointless to write functions, when
we can use string concatenation or sprintf already. Right?

NB: Though, it might be good to have a simple utility function to speed things along.

So lets look at a union example where we want to find all users with the last names of
Baker and Flynn. Below is what the query will be:

  


 
   
Now all we need to do is build two queries, filtering on Baker and Flynn respectively, then
combine them together with UNION, execute them, and were done. So lets do that.





 
 


 
 



 
 
 




We can take the same approach with INTERSECT and EXCEPT queries. Wed replace
UNION with either INTERSECT or EXCEPT, giving us the query that we desired. If youre
not familiar with these, heres two quotes from the Wikipedia link above:

The SQL INTERSECT operator takes the results of two queries and returns
only rows that appear in both result sets

The SQL EXCEPT operator takes the distinct rows of one query and returns
the rows that do not appear in a second result set

Well, we could, if MySQL supported them that is. It doesnt. But Im including this section
because theyre supported by other RDBMSs, including Oracle, MSSQLServer and
PostgreSQL.

NB: Most database examples I write are based around MySQL, because its rather
synonymous with PHP. However, its not the only game in town and I dont assume that
its all youre using.

&RQFOXVLRQ
By part two of this series, you have enough to build a robust range of SQL queries in your
applications. In the third part, well drop right back to the basics of using Select, including
having, order and limit clauses. Dont forget, check out part one
(http://www.masterzendframework.com/tutorial/zend-db-sql-select-easy-where-clauses)
on building Where clauses, if youve come straight here.

So tell me your opinion. Is Zend\Db\Sql\Select a really simple library to use to construct


queries? Are they as hard as you thought they would be? Add a comment with your
opinion.

See you next week!

f Share    KWWSZZZPDVWHU]HQGIUDPHZRUNFRP
T Tweet    KWWSZZZPDVWHU]HQGIUDPHZRUNFRPDPSWH[W E\#VHWWHUPMG
g    KWWSSOXVJRRJOHFRPVKDUH"XUO KWWSZZZPDVWHU]HQGIUDPHZRUNFRP

/LNH7KDW"
Dont miss the next post. Drop your email in the box below, and get it straight to your
inbox, PLUS exclusive content only available by email. No spam, and you can
unsubscribe at any time.

<RXU(PDLO$GGUHVV

Send Me Those Posts!

&RPPHQWV
5HFRPPHQG

0DVWHU=HQG)UDPHZRUN

6KDUH

/RJLQ

6RUWE\%HVW

6WDUWWKHGLVFXVVLRQ

%HWKHILUVWWRFRPPHQW

:+$7
67+,6"

$/62210$67(5=(1')5$0(:25.

+RZWR8VH&RQVWUXFWRU,QMHFWLRQ,Q=)
FRPPHQWV\HDUVDJR

,DQ7KHDGYDQWDJHRIXVLQJFRQFUHWH

6LPSOLI\LQJ8QLW7HVWLQJ DQGDVNLQJIRU
KHOSZKHQQHHGHG
FRPPHQWV\HDUVDJR

IDFWRU\FODVVHVRYHUFORVXUHVIRU',LVWKDW
\RXUFRQILJFDQEHFDFKHG

+RZ7R7UDQVODWH&RQWHQW:LWK7KH
7UDQVODWH9LHZ+HOSHU

0DWWKHZ6HWWHU*UHDWWRKHDU

#MHDQFDUORPDFKDGR$Q\WKLQJHOVH\RX
OLNHG"

FRPPHQWVD\HDUDJR

?=HQG?'E?6TO%XLOG64/:KHUH&ODXVHV
(DVLO\DQG(IILFLHQWO\0DVWHU=HQG
)UDPHZRUN
FRPPHQWPRQWKVDJR

$YDWDU0DWWKHZ6HWWHU+L$UYLQGVRUU\IRUWKH
GHOD\LQJHWWLQJEDFNWR\RX)LUVWTXHVWLRQ
ZK\DUH\RXDWWHPSWLQJWRDFFHVV
SXEOLFDSSOLFDWLRQ"SXEOLF

$YDWDU(OOLRWW9HUQRQ-XVWZDQWWRWKDQN\RXIRU
WKLV7KLV=HQG?'E?6TO$3,ORRNVOLNHRQHRI
WKRVHWKLQJVWKDWPDNHV\RXZDQWWRZHHSDW
ILUVWDQGWKHQ\RXJHW

6XEVFULEH

$GG'LVTXVWR\RXUVLWH$GG'LVTXV$GG

JOIN THE COMMUNITY


'URS\RXUHPDLODGGUHVVLQWKHER[EHORZ
WRMRLQDFRPPXQLW\RIRYHUOLNH
PLQGHGGHYHORSHUVJHWWLQJJUHDWWXWRULDOV
SRGFDVWVVFUHHQFDVWVWLSVSRLQWHUVDQG
PXFKPXFKPRUH

\RXUHPDLODGGUHVV

6XEPLW

3ULYDF\

SPONSORS

(http://www.sitepoint.com)

(http://fre.ag/42u3m4o5)

2016 Master Zend Framework

Contact Us (/contact) / Terms and Conditions (/terms-andconditions) / Privacy Policy (/privacy-policy) / Disclaimer
(/disclaimer) / Copyright (/copyright) / Guest Posting
(/guest-posting) / Impressum (/impressum)

You might also like