<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Laughing Meme &#187; sql</title>
	<atom:link href="http://laughingmeme.org/tag/sql/feed/" rel="self" type="application/rss+xml" />
	<link>http://laughingmeme.org</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Sun, 29 Jan 2012 21:54:39 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Liminal Existence: SELECT * FROM everything, or why databases are awesome.</title>
		<link>http://laughingmeme.org/2007/06/25/liminal-existence-select-from-everything-or-why-databases-are-awesome/</link>
		<comments>http://laughingmeme.org/2007/06/25/liminal-existence-select-from-everything-or-why-databases-are-awesome/#comments</comments>
		<pubDate>Mon, 25 Jun 2007 16:57:13 +0000</pubDate>
		<dc:creator>Kellan</dc:creator>
				<category><![CDATA[Aside]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[databases]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[scalability]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://laughingmeme.org/2007/06/25/liminal-existence-select-from-everything-or-why-databases-are-awesome/</guid>
		<description><![CDATA[Blaine continues the work of making Rails scale beyond its &#8220;for 3000 of your closet friends&#8221; default scale. I expect to see some FORCE INDEX patches coming out of some recent chats we&#8217;ve had.]]></description>
			<content:encoded><![CDATA[<p>Blaine continues the work of making Rails scale beyond its &#8220;for 3000 of your closet friends&#8221; default scale.  I expect to see some <code>FORCE INDEX</code> patches coming out of some recent chats we&#8217;ve had.</p>
<p><a href='http://romeda.org/blog/2007/06/select-from-everything-or-why-databases.html'>http://romeda.org/blog/2007/06/select-from-everything-or-why-databases.html</a></p>]]></content:encoded>
			<wfw:commentRss>http://laughingmeme.org/2007/06/25/liminal-existence-select-from-everything-or-why-databases-are-awesome/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>In Lieu of the Promised Article on Tags and SQL</title>
		<link>http://laughingmeme.org/2005/04/07/in-lieu-of-the-promised-article-on-tags-and-sql/</link>
		<comments>http://laughingmeme.org/2005/04/07/in-lieu-of-the-promised-article-on-tags-and-sql/#comments</comments>
		<pubDate>Thu, 07 Apr 2005 15:19:11 +0000</pubDate>
		<dc:creator>Kellan</dc:creator>
				<category><![CDATA[rails]]></category>
		<category><![CDATA[sql]]></category>
		<category><![CDATA[tagging]]></category>
		<category><![CDATA[tags]]></category>

		<guid isPermaLink="false">http://lm.quxx.info/?p=1065</guid>
		<description><![CDATA[For the folks I promised an article on how to implements tags in SQL. Sorry, I never finished it. I got sucked into some more esoteric problems, and never got back to writing down the basics. However, all is not lost. Peter has done a very nice job of writing about how he implemented tagging [...]]]></description>
			<content:encoded><![CDATA[<p>For the folks I promised an article on how to implements tags in SQL.  Sorry, I never finished it.  I got sucked into some more esoteric problems, and never got back to writing down the basics.  However, all is not lost.  <a href="http://www.petercooper.co.uk">Peter</a> has done a very nice job of writing about how he implemented tagging for his <a href="http://www.bigbold.com/snippets/">snippets code libraries</a>.</p>

<ol>
<li><p><a href="http://www.petercooper.co.uk/archives/000648.html">Matching on data intersection across a many-to-many join</a> &#8211; aka, how to find an object (e.g. a post or a recipe) with two or more tags (i.e. show my all posts tagged with <code>tagging</code> and <code>sql</code>).  For the lazy, skip to bottom for a solution. (but it&#8217;s worth reading through) This is what enables <a href="http://laughingmeme.org/archives/002734.html#002734">tag combos</a>. (Also available <a href="http://www.bigbold.com/snippets/posts/show/32">from snippets</a>)</p></li>
<li><p><a href="http://www.bigbold.com/snippets/posts/show/35">Find items with similar (or as many as possible) relationships &#8211; for a &#8216;related posts&#8217; box etc</a> &#8211; aka, find other recipes tagged with similar tags to the recipe I&#8217;m currently looking at I&#8217;m currently looking at.  In <a href="http://laughingmeme.org/archives/002842.html#002842">Recipes on Rails</a>, if I&#8217;m looking at my recipe for hot chocolate (tags: <code>beverage</code>, <code>hot</code>, <code>chocolate</code>), use this query to also show tea and coffee. (both tagged <code>beverage</code> and <code>hot</code>)</p></li>
<li><p><a href="http://www.bigbold.com/snippets/posts/show/34">Find all many-to-many relationships which are tied to an arbitrary number of other many-to-many relationships</a> &#8211; I&#8217;m looking at all recipes with the tags <code>easy</code>, and <code>hot</code>, what are related tags I could use?  How about <code>carrot</code>, and <code>curry</code> (my curry carrot soup is tagged <code>easy</code>, <code>soup</code>, <code>carrot</code>, and <code>curry</code>, not to mention <code>winter</code> and <code>favorite</code>), or maybe <code>silly</code> with which I&#8217;ve tagged my boiled water recipe.<br />
After some futzing I came up with the same query that Peter did, but I was really hoping there was another solution, as I&#8217;ve been seeing some of the same <a href="http://www.peerfear.org/rss/permalink/2005/04/02/BrokenMySQLSubqueries/">worrying numbers using MySQL 4.1.x&#8217;s subqueries</a> that Kevin is.</p></li>
</ol>

<p>There you go, you no longer have any excuse for building a sub-par tagging system.</p>

<p>fyi, <a href="http://www.petercooper.co.uk/">Peter</a>, from whom all those tips originate, on top of being the creator of the <a href="http://bigbold.com/snippets/">snippets</a> site, is <a href="http://www.petercooper.co.uk/archives/000662.html">available for hire</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://laughingmeme.org/2005/04/07/in-lieu-of-the-promised-article-on-tags-and-sql/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>ActiveRecord as explained by a Hibernate hacker.</title>
		<link>http://laughingmeme.org/2005/03/31/activerecord-as-explained-by-a-hibernate-hacker/</link>
		<comments>http://laughingmeme.org/2005/03/31/activerecord-as-explained-by-a-hibernate-hacker/#comments</comments>
		<pubDate>Thu, 31 Mar 2005 17:33:26 +0000</pubDate>
		<dc:creator>Kellan</dc:creator>
				<category><![CDATA[Aside]]></category>
		<category><![CDATA[activerecord]]></category>
		<category><![CDATA[orm]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://lm.quxx.info/?p=2893</guid>
		<description><![CDATA[A more balanced article would have mentioned how painful it is to do queries in a &#8216;SQL-like&#8217; language. Impossible to debug, stuff of nightmares]]></description>
			<content:encoded><![CDATA[<p>A more balanced article would have mentioned how painful it is to do queries in a &#8216;SQL-like&#8217; language.  Impossible to debug, stuff of nightmares</p>
<p><a href='http://web1.theserverside.com/articles/article.tss?l=RailsHibernate'>http://web1.theserverside.com/articles/article.tss?l=RailsHibernate</a></p>]]></content:encoded>
			<wfw:commentRss>http://laughingmeme.org/2005/03/31/activerecord-as-explained-by-a-hibernate-hacker/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL, and the CASE for Class Table Inheritance</title>
		<link>http://laughingmeme.org/2004/08/14/mysql-and-the-case-for-class-table-inheritance/</link>
		<comments>http://laughingmeme.org/2004/08/14/mysql-and-the-case-for-class-table-inheritance/#comments</comments>
		<pubDate>Sun, 15 Aug 2004 01:08:00 +0000</pubDate>
		<dc:creator>Kellan</dc:creator>
				<category><![CDATA[case]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[eaa]]></category>
		<category><![CDATA[enterprise]]></category>
		<category><![CDATA[Longer]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[oop]]></category>
		<category><![CDATA[patterns]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://lm.quxx.info/?p=883</guid>
		<description><![CDATA[At work we&#8217;re using Class Table Inheritance to model the core data structures of our as yet nameless open source CRM. (actually it has a code name, but I don&#8217;t like it, so we&#8217;ll pretend it&#8217;s nameless) This week as I learned both the name of this pattern, and the SQL to implement it efficiently [...]]]></description>
			<content:encoded><![CDATA[<p>
At <a href="http://groundspring.org">work</a> we&#8217;re using <a href="http://martinfowler.com/eaaCatalog/classTableInheritance.html">Class Table Inheritance</a> to model the core data structures of our as yet nameless open source <acronym title="Community Relationship Management">CRM</acronym>. (actually it has a code name, but I don&#8217;t like it, so we&#8217;ll pretend it&#8217;s nameless)  
</p>

<p><p>
This week as I learned both the name of this pattern, and the SQL to implement it efficiently in MySQL I thought I&#8217;d share some notes on what we&#8217;ve come up with.
</p>
<span id="more-883"></span>
<p>
<h3>Class Table Inheritance</h3>
<acronym title="Class Table Inheritance">CTI</acronym> is a pattern where your schema  hews closely to the your class hierarchy &#8212; you have a table for each class, and object attributes are stored as columns in the table for that class.  This is as opposed to <a href="http://www.martinfowler.com/eaaCatalog/singleTableInheritance.html">Single Table Inheritance</a>, which stores all attributes for every member of an inheritance tree in a single table, or <a href="http://www.martinfowler.com/eaaCatalog/concreteTableInheritance.html">Concrete Table Inheritance</a> which duplicates the inherited fields to each table.
</p>
<p>
We&#8217;re using CTI for a number of reasons, some excellent, and some because that is how our brains work.  One key benefit is we get the ability to operate on heterogenous collections of object. (i.e. display a sorted list of contact objects irrespective of whether they are individuals, organizations, etc.)  The fact that something as fundamental as polymorphism can be difficult to accomplish using other O/R techniques hilights the general difficulty and <a href="http://www.google.com/search?q=impedance+mismatch" title="6 of the first 10 results are about O/R">impedance mismatch</a> of object to relational mapping.
</p>
<p>
There are, however a few challenges involved. 
</p>
<p>
<h3>The Model</h3>
But quickly a trivial mock up of the data model to give us something to play with.  In this model we have 3 classes, a base Contact class, and 2 types of contacts Individual and Organization which inherit from Contact.  In the database we model this as a Contact table, with a primary id, and any fields which the Contact the parent class provides.  Individual and Organization each get their own table, with class specific attributes, plus the primary id from Contact which is both the primary id, and a foreign key into Contact.  For every contact stored in the database there is a record in the Contact table, and a record in either Individual or Organization.
</p>
<p>
<img src="http://laughingmeme.org/img/simple_contact_model.gif" />
</p>
<p>
<h3>Challenge 1:</h3>
How do you retrieve your data now that it is broken across multiple tables?  The obvious (and obviously wrong) solution would be to first select against the Contact table, examine the resulting data, and select against the appropriate children tables. (remember this example is a drastically simplified data model)
</p>
<p>
<h3>Solution 1:</h3>
My current solution is to do a 3 way left outer join, and then instantiate the objects out of fields which aren&#8217;t null.  It can look a bit ugly with large numbers of columns, but is actually pretty simple, and initial benchmarks against a test data set of 1.3 million records suggests it scales nicely.</p>

<pre>
SELECT 
  c.id as id, c.contactType,
  i.firstName, i.lastName,
  o.name as orgName
FROM
  Contact as c
LEFT JOIN Individual as i ON i.id = c.id 
LEFT JOIN Organization as o ON o.id = c.id
</pre>

<p>(And it&#8217;s pretty easy to coax the necessary SQL out of our modified version of <a href="http://pear.php.net/package/DB_DataObject">DB_DataObject</a>. I&#8217;ll demonstrate that in a future entry)
</p>
<p>
<h3>Challenge 2:</h3>
One of the good reasons (in fact the only concrete one I&#8217;ve given you) to go with CTI and its potential added complexity is the desire to sort a mixed list of contact types.   But what do you do when you want to sort on an amorphous concept like &#8220;Name&#8221;?  Individual might sort by &#8220;Lastname, Firstname&#8221;, while we just use &#8220;orgName&#8221; for an organization.  Where is our polymorphism now?
</p>
<p>
One solution would be select all known records, and do sorting and slicing at the application level.  (This is so wrong it makes my head hurt)  Another solution would be store a field like &#8220;sortName&#8221; on Contact, which you could calculate and save on inserts and updates.  This is on the right track.
</p>
<p>
<h3>Solution 2:</h3>
The solution (which <a href="http://blogs.onenw.org/carl">Carl</a> clued me into while we waited to get into the zoo), is to use the <a href="http://dev.mysql.com/doc/mysql/en/Control_flow_functions.html">SQL CASE statement</a> to calculate &#8220;sortName&#8221; on the fly.  Below is our SQL from below with the new logic in green.</p>

<pre>
SELECT 
  c.id as id, c.contactType,
  i.firstName, i.lastName,
  o.name as orgName<span style="color:green;">,
CASE 
 WHEN c.contactType = 'Individual' THEN CONCAT(i.lastName, i.firstName)
 WHEN c.contactType = 'Organization' THEN o.name
END as sortName</span>
FROM
  Contact as c
LEFT JOIN Individual as i ON i.id = c.id 
LEFT JOIN Organization as o ON o.id = c.id
<span style="color:green;">ORDER by sortName</span>
</pre>

<p></p>
<p>
This simply adds a switch statement to your field list conditionally setting the value of sortName.
</p>
<p>
There is nothing quite so satisfying as finding the right tool for the right job.  I&#8217;m currently totally in love with the CASE statement, and think everyone should know about it. (hence this bit of evangelism)
</p>
<p>
Tip: don&#8217;t forget that &#8216;,&#8217; after orgName, I keep forgetting it and wondering why my SQL isn&#8217;t working.
</p>
<p>
So concludes today&#8217;s edition of &#8220;Enterprise Development with MySQL&#8221; (&#8220;Kellan Learns SQL&#8221; didn&#8217;t sound as impressive).  In the near future I hope to get a chance to write up some of the PHP libs we&#8217;ve been building/modifying to support object rich web development techniques, completing the picture. (<acronym title="Objects Linux Apache MySQL PHP">OLamp</acronym> anyone?)
</p>
<p>
<h3>Mixing Metaphors</h3>
Single, and Concrete <acronym title="Table Inheritance">TI</acronym> both have their places, and the good news is you can mix these patterns without much difficulty.  Still I&#8217;m happy with both the flexibility and &#8220;OO-ness&#8221; of Concrete Table Inheritance, and once again impressed by the speed, and power of MySQL. (N.B. we&#8217;re targeting 4.1.x, but these above examples all work with 4.0.16 and 4.0.20)
</p></p>
]]></content:encoded>
			<wfw:commentRss>http://laughingmeme.org/2004/08/14/mysql-and-the-case-for-class-table-inheritance/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>The CASE statement *is* supported in MySQL 4.0.x series (docs imply MySQL 5.0)</title>
		<link>http://laughingmeme.org/2004/08/12/the-case-statement-is-supported-in-mysql-40x-series-docs-imply-mysql-50/</link>
		<comments>http://laughingmeme.org/2004/08/12/the-case-statement-is-supported-in-mysql-40x-series-docs-imply-mysql-50/#comments</comments>
		<pubDate>Fri, 13 Aug 2004 02:28:27 +0000</pubDate>
		<dc:creator>Kellan</dc:creator>
				<category><![CDATA[Aside]]></category>
		<category><![CDATA[case]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://lm.quxx.info/?p=2458</guid>
		<description><![CDATA[CASE is one of the coolest, most useful SQL constructs ever, more people should use it.]]></description>
			<content:encoded><![CDATA[<p>CASE is one of the coolest, most useful SQL constructs ever, more people should use it.</p>
<p><a href='http://dev.mysql.com/doc/mysql/en/Control_flow_functions.html'>http://dev.mysql.com/doc/mysql/en/Control_flow_functions.html</a></p>]]></content:encoded>
			<wfw:commentRss>http://laughingmeme.org/2004/08/12/the-case-statement-is-supported-in-mysql-40x-series-docs-imply-mysql-50/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

