<?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/"
	>

<channel>
	<title>Dancing Mammoth</title>
	<atom:link href="http://dancingmammoth.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://dancingmammoth.com</link>
	<description>Cleaner Websites for a Cleaner Future</description>
	<pubDate>Mon, 15 Jun 2009 16:24:51 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>In Which the Summer Mammoth Introduces Himself&#8230;</title>
		<link>http://dancingmammoth.com/2009/06/15/in-which-the-summer-mammoth-introduces-himself/</link>
		<comments>http://dancingmammoth.com/2009/06/15/in-which-the-summer-mammoth-introduces-himself/#comments</comments>
		<pubDate>Mon, 15 Jun 2009 15:57:35 +0000</pubDate>
		<dc:creator>Tim Lee</dc:creator>
		
		<category><![CDATA[Miscellaneous]]></category>

		<guid isPermaLink="false">http://dancingmammoth.com/?p=217</guid>
		<description><![CDATA[My name is Tim and I&#8217;ll be a part of the Dancing Mammoth team for the summer. During the school year I&#8217;m a PhD student in computer science at Princeton, working with these fine folks. Princeton keeps us pretty busy during the school year, but during the summer, they turn us loose and force us [...]]]></description>
			<content:encoded><![CDATA[<p>My name is Tim and I&#8217;ll be a part of the Dancing Mammoth team for the summer. During the school year I&#8217;m a PhD student in computer science at Princeton, working with <a href="http://citp.princeton.edu/">these fine folks.</a> Princeton keeps us pretty busy during the school year, but during the summer, they turn us loose and force us to fend for ourselves in the &#8220;real world.&#8221;</p>
<p>I&#8217;ve been doing web development on and off for more than a decade. During college, I was the webmaster of the University of Minnesota&#8217;s computer science department, where I developed a variety of web applications and gave <a href="http://www.cs.umn.edu/">our department website</a> a fresh new look (recently replaced by an even fresher, newer look). I got lots of practice with Apache, Perl, JavaScript, MySQL, and the usual alphabet soup of three- and four-letter acronyms. More recently, I&#8217;ve gotten into web development using Python and the Django framework.</p>
<p>After college, I worked as a journalist, blogger, and policy analyst, writing for <a href="http://arstechnica.com/authors/timothy-b-lee/"><em>Ars Technica</em></a>, the <a href="http://roomfordebate.blogs.nytimes.com/2009/02/18/facebook-rules/"><em>New York Times</em></a>, <a href="http://www.slate.com/id/2184367/"><em>Slate</em></a>, the <a href="http://www.cato.org/pub_display.php?pub_id=9775">Cato Institute,</a> and <a href="http://www.techdirt.com/">various</a> <a href="http://freedom-to-tinker.com/">other</a> <a href="http://showmeinstitute.org/scholar/id.24/staff_detail.asp">places.</a> Writing prose is fun, but after a few years I started to miss writing code and decided to go back to grad school.</p>
<p>For years, PJ has provided web design and hosting services to a number of my favorite <a href="http://www.theagitator.com/">blogs</a> (including one I <a href="http://www.techliberation.com/">contribute to</a>), <a href="http://reason.tv/">magazines</a>, and non-profits and I&#8217;ve always been impressed by his minimalist design sense and bulletproof hosting methodology. So I was excited when he invited me to join the team for the summer. I&#8217;m expecting to learn a lot about web development while helping clients solve their problems.</p>
]]></content:encoded>
			<wfw:commentRss>http://dancingmammoth.com/2009/06/15/in-which-the-summer-mammoth-introduces-himself/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Wanted: Junior Developer/Proboscidean</title>
		<link>http://dancingmammoth.com/2009/02/16/wanted-junior-developer/</link>
		<comments>http://dancingmammoth.com/2009/02/16/wanted-junior-developer/#comments</comments>
		<pubDate>Mon, 16 Feb 2009 21:59:44 +0000</pubDate>
		<dc:creator>Gary DuVall</dc:creator>
		
		<category><![CDATA[Miscellaneous]]></category>

		<category><![CDATA[careers]]></category>

		<guid isPermaLink="false">http://dancingmammoth.com/?p=213</guid>
		<description><![CDATA[Are you comfortable talking to important people at 9:00am in your underwear? Have you ever wanted to get to know your home more intimately? Dancing Mammoth, a web development firm based in Reston, VA, is seeking a self-starting, highly-responsible Junior Developer to work from home with demonstrated skills in the following areas:

PHP 5 (OOP skills [...]]]></description>
			<content:encoded><![CDATA[<p>Are you comfortable talking to important people at 9:00am in your underwear? Have you ever wanted to get to know your home more intimately? Dancing Mammoth, a web development firm based in Reston, VA, is seeking a self-starting, highly-responsible Junior Developer to work from home with demonstrated skills in the following areas:</p>
<ul>
<li>PHP 5 (OOP skills a requirement)</li>
<li>MySQL 5</li>
<li>XHTML</li>
<li>CSS</li>
<li>JavaScript</li>
<li>JQuery</li>
<li>Python experience a plus.</li>
</ul>
<p>The right candidate will fit right in with our fast-paced virtual office environment and be able to hit the ground running with our varied base of clients and growing stable of in-house initiatives. We&#8217;re preferential to applicants in or around Chicago, Washington D.C., or Reston, VA but will consider other areas for the right person. Starting salary will be commensurate with experience, talent, and knowledge of the movie Xanadu.</p>
<p>Interested? Feel compelled to make your mark? We&#8217;d like to hear from you! Send your resume to <a href="careers@dancingmammoth.com">careers@dancingmammoth.com</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://dancingmammoth.com/2009/02/16/wanted-junior-developer/feed/</wfw:commentRss>
		</item>
		<item>
		<title>When You Have Your Own Iconic Brand&#8230;</title>
		<link>http://dancingmammoth.com/2009/01/16/when-you-have-your-own-iconic-brand/</link>
		<comments>http://dancingmammoth.com/2009/01/16/when-you-have-your-own-iconic-brand/#comments</comments>
		<pubDate>Fri, 16 Jan 2009 23:42:57 +0000</pubDate>
		<dc:creator>PJ Doland</dc:creator>
		
		<category><![CDATA[Miscellaneous]]></category>

		<category><![CDATA[design]]></category>

		<category><![CDATA[Theft]]></category>

		<guid isPermaLink="false">http://dancingmammoth.com/?p=200</guid>
		<description><![CDATA[Did Gibson think that nobody would notice when they completely-ripped off Apple for  their new website design?

 
For reference, here is a screencap of Apple&#8217;s site:

 
Which brings me to two points:

When you have your own iconic brand, you really shouldn&#8217;t need to steal so shamelessly.
It&#8217;s 2009, Gibson. Did you really think table-based layout was still a [...]]]></description>
			<content:encoded><![CDATA[<p>Did <a href="http://gibson.com/">Gibson</a> think that nobody would notice when they completely-ripped off Apple for  their new website design?</p>
<p style="text-align: center;"><a href="http://gibson.com/"><img class="size-large wp-image-207 aligncenter" title="Gibson's New Site" src="http://dancingmammoth.com/wp-content/uploads/090116-gibson-1024x899.png" alt="Gibson's New Site" width="614" height="539" /></a></p>
<p align="center"> </p>
<p>For reference, here is a screencap of <a href="http://apple.com">Apple&#8217;s</a> site:</p>
<p style="text-align: center;"><a href="http://apple.com"><img class="size-large wp-image-209 aligncenter" title="Apple's Current Site" src="http://dancingmammoth.com/wp-content/uploads/090116-apple-1024x899.png" alt="Apple's Current Site" width="614" height="539" /></a></p>
<p align="center"> </p>
<p>Which brings me to two points:</p>
<ol>
<li>When you have your own iconic brand, you really shouldn&#8217;t need to steal so shamelessly.</li>
<li>It&#8217;s 2009, Gibson. Did you really think table-based layout was still a good idea?</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://dancingmammoth.com/2009/01/16/when-you-have-your-own-iconic-brand/feed/</wfw:commentRss>
		</item>
		<item>
		<title>No Need for Wax, IWF Is Shiny Enough</title>
		<link>http://dancingmammoth.com/2009/01/06/no-need-for-wax-iwf-is-shiny-enough/</link>
		<comments>http://dancingmammoth.com/2009/01/06/no-need-for-wax-iwf-is-shiny-enough/#comments</comments>
		<pubDate>Tue, 06 Jan 2009 22:35:55 +0000</pubDate>
		<dc:creator>Matt Fetissoff</dc:creator>
		
		<category><![CDATA[Case Studies]]></category>

		<guid isPermaLink="false">http://dancingmammoth.com/?p=170</guid>
		<description><![CDATA[The Independent Women&#8217;s Forum came to us in early 2007 for an update on their site design and ended up with the sparkly interface you now see. The design of the site lends itself nicely for a journey through the magical land of color distribution. So grab a cup of coffee and buckle up as [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://iwf.org" target="_blank"><img class="alignright size-medium image" title="iwf" src="http://dancingmammoth.com/wp-content/uploads/iwf-318x270.gif" alt="" width="318" height="270" /></a><a href="http://iwf.org" target="_blank">The Independent Women&#8217;s Forum</a> came to us in early 2007 for an update on their site design and ended up with the sparkly interface you now see. The design of the site lends itself nicely for a journey through the magical land of color distribution. So grab a cup of coffee and buckle up as the ride begins.</p>
<p>To help explain what we mean by color distribution, take a look at this <a href="/wp-content/uploads/iwf-colormap.gif">little map</a> we created using IWF.org as a base.</p>
<p>On occasion, we start layouts by grabbing all the content the client would like to see on the main page, making it black, and dumping it all into a new Photoshop file. Next, we make textual hierarchy changes by pumping up the weight and size for headings and subheadings. After some spacing and alignment changes its ready, but start collecting color only after these steps have been completed</p>
<p><img class="floatleft" src="http://dancingmammoth.com/wp-content/uploads/iwf1.gif" alt="" />First,  we establish any existing colors which will need to be incorporated into our palette due to existing branding. In the example using IWF.org, the red from the logo needed to be added.</p>
<p><img class="floatleft" src="http://dancingmammoth.com/wp-content/uploads/iwf3.gif" alt="" />We needed to pay attention to an additional client request, which was that we keep the site feeling open and bright. Yellow or yellow used as a gradient is good for this.</p>
<p><img class="floatleft" src="http://dancingmammoth.com/wp-content/uploads/iwf5.gif" alt="" /><img class="floatleft" src="http://dancingmammoth.com/wp-content/uploads/iwf4.gif" alt="" />You can add two colors to the palette by choosing one with a rich hue (aka saturation), in this case blue, then <a href="http://dancingmammoth.com/wp-content/uploads/blues.png" target="_blank">branch off by grabbing a tint of the same hue</a>.</p>
<p><img class="floatleft" src="http://dancingmammoth.com/wp-content/uploads/iwf2.gif" alt="" />We also always grab something fairly neutral to use as borders, or for headings and backgrounds which require less emphasis than areas with brighter hues. For IWF.org, we chose a medium gray that is used on all borders and dividing lines.</p>
<p>Now the color palette is ready. Most, if not all of your color usage will be dictated by the palette. You can deviate, but only by shifting the base hue with shades and tints. Start by identifying which elements should use the same color. For example, all links within the main content area need the same color. All first-level headings need the same color as well.</p>
<p>Now you can experiment by using the colors in your palette in these positions. Any colors that are too light can be used for text as long as there is a background behind it with good color contrast to make everything readable.</p>
<p>Remember to use white as a color as well, not just for backgrounds. Any of the colors in your palette can be used for a background, which means any text on top of it can be white (depending on readability).</p>
]]></content:encoded>
			<wfw:commentRss>http://dancingmammoth.com/2009/01/06/no-need-for-wax-iwf-is-shiny-enough/feed/</wfw:commentRss>
		</item>
		<item>
		<title>ShoutingMat.ch</title>
		<link>http://dancingmammoth.com/2008/12/30/shoutingmatch/</link>
		<comments>http://dancingmammoth.com/2008/12/30/shoutingmatch/#comments</comments>
		<pubDate>Tue, 30 Dec 2008 22:49:25 +0000</pubDate>
		<dc:creator>Matt Fetissoff</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://dancingmammoth.com/?p=149</guid>
		<description><![CDATA[As described on the about page, ShoutingMat.ch is a civilized retreat untainted by the excesses and whims of the mob.
Huh? Let me explain:
Sites like digg.com and reddit pull in data by relying on a unorganized rabble of internet misfits to strain good internet content from the bad. ShoutingMat.ch looks to a definitive list of the [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://shoutingmat.ch/" target="_blank"><img class="alignright size-medium image" title="shouting" src="http://dancingmammoth.com/wp-content/uploads/shouting-307x270.jpg" alt="" width="307" height="270" /></a>As described on the about page, <a href="http://shoutingmat.ch/" target="_blank">ShoutingMat.ch</a> is a civilized retreat untainted by the excesses and whims of the mob.</p>
<p>Huh? Let me explain:</p>
<p>Sites like <em>digg.com</em> and <em>reddit</em> pull in data by relying on a unorganized rabble of internet misfits to strain good internet content from the bad. ShoutingMat.ch looks to a definitive list of the blogs that everyone&#8217;s reading, bottling you only the best content from purest sources in the ice cold mountains.</p>
<p>Not only will you drink up high quality content, but each story delivers the blog or origin from whence it came, accessible via a handy drop-down list so simple even a caveman could figure it out.</p>
<p>Here. Me make drawing<br />
<img class="alignnone size-full wp-image-153" title="shoutingmatch-diagram" src="http://dancingmammoth.com/wp-content/uploads/shoutingmatch-diagram.gif" alt="" /></p>
]]></content:encoded>
			<wfw:commentRss>http://dancingmammoth.com/2008/12/30/shoutingmatch/feed/</wfw:commentRss>
		</item>
		<item>
		<title>A Clean New Direction for American Spectator</title>
		<link>http://dancingmammoth.com/2008/11/26/a-new-direction-for-american-spectator/</link>
		<comments>http://dancingmammoth.com/2008/11/26/a-new-direction-for-american-spectator/#comments</comments>
		<pubDate>Wed, 26 Nov 2008 20:12:56 +0000</pubDate>
		<dc:creator>Matt Fetissoff</dc:creator>
		
		<category><![CDATA[Case Studies]]></category>

		<category><![CDATA[color distribution]]></category>

		<category><![CDATA[design]]></category>

		<category><![CDATA[readability]]></category>

		<guid isPermaLink="false">http://dancingmammoth.com/?p=129</guid>
		<description><![CDATA[Spectator.org is the newest addition to the list of sites we&#8217;ve designed and built.
Since The American Spectator has been around for 1967, keeping the established identity was an important part of the design process. We retained their look by re-using the existing color palette and by keeping the established logo simple in a basic white [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.spectator.org/" target="_blank"><img class="alignright size-medium image" title="spectator11" src="http://dancingmammoth.com/wp-content/uploads/spectator11-302x270.jpg" alt="" width="302" height="270" /></a><a href="http://www.spectator.org/" target="_blank">Spectator.org</a> is the newest addition to the list of sites we&#8217;ve designed and built.</p>
<p>Since The American Spectator has been around for 1967, keeping the established identity was an important part of the design process. We retained their look by re-using the existing color palette and by keeping the established logo simple in a basic white on red header. Further distributing the red, we threw it into the date-bars, content category headings, third column headings, and buttons. Using the black in the large featured post area serves as the focal point, drawing the eye with an over-sized image and further distributing color. We continued this with the bold black post headings and the background for the active state of the nav list in the right column.</p>
<p>We were also tasked with keeping a good chunk of the content available on the main page without a ton of scrolling. To accomplish this, we kept the spacing between posts on the homepage to a minimum. This expands of course when you click through to read the full article. To create visual separation of content, we used thin borders on the bottom of each post and kept the article headings big compared to the accompanying text.</p>
<p>Along with the re-design, this site has been built on a newly built backend framework which allows for much greater content control by the editors. Additions to the backend are super simple now as well, so any client changes/requests can be managed quickly and efficiently.</p>
]]></content:encoded>
			<wfw:commentRss>http://dancingmammoth.com/2008/11/26/a-new-direction-for-american-spectator/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Bringing Site Control Out of the Admin Interface</title>
		<link>http://dancingmammoth.com/2008/11/20/bringing-site-control-out-of-the-admin-interface/</link>
		<comments>http://dancingmammoth.com/2008/11/20/bringing-site-control-out-of-the-admin-interface/#comments</comments>
		<pubDate>Thu, 20 Nov 2008 18:20:35 +0000</pubDate>
		<dc:creator>PJ Doland</dc:creator>
		
		<category><![CDATA[Lab]]></category>

		<category><![CDATA[Diderot]]></category>

		<category><![CDATA[UI]]></category>

		<category><![CDATA[Usability]]></category>

		<guid isPermaLink="false">http://dancingmammoth.com/?p=156</guid>
		<description><![CDATA[Sometimes it just makes more sense to put the controls right on the site. Watch this quick screencast to find out how we let one of our clients order the stories in their main content well with drag &#38; drop ease.

Bringing Site Control Out of the Admin Interface from Dancing Mammoth on Vimeo.
]]></description>
			<content:encoded><![CDATA[<p>Sometimes it just makes more sense to put the controls right on the site. Watch this quick screencast to find out how we let one of our clients order the stories in their main content well with drag &amp; drop ease.</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="640" height="360" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://vimeo.com/moogaloop.swf?clip_id=2298531&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=c9ff23&amp;fullscreen=1" /><embed type="application/x-shockwave-flash" width="640" height="360" src="http://vimeo.com/moogaloop.swf?clip_id=2298531&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=c9ff23&amp;fullscreen=1" allowscriptaccess="always" allowfullscreen="true"></embed></object><br />
<a href="http://vimeo.com/2298531">Bringing Site Control Out of the Admin Interface</a> from <a href="http://vimeo.com/user955084">Dancing Mammoth</a> on <a href="http://vimeo.com">Vimeo</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://dancingmammoth.com/2008/11/20/bringing-site-control-out-of-the-admin-interface/feed/</wfw:commentRss>
		</item>
		<item>
		<title>All the Little Birds on Jaybird Street, Love to Hear the Mammoth Go Tweet, Tweet, Tweet.</title>
		<link>http://dancingmammoth.com/2008/11/14/all-the-little-birds-on-jaybird-street-love-to-hear-the-mammoth-go-tweet-tweet-tweet/</link>
		<comments>http://dancingmammoth.com/2008/11/14/all-the-little-birds-on-jaybird-street-love-to-hear-the-mammoth-go-tweet-tweet-tweet/#comments</comments>
		<pubDate>Fri, 14 Nov 2008 23:27:00 +0000</pubDate>
		<dc:creator>PJ Doland</dc:creator>
		
		<category><![CDATA[Miscellaneous]]></category>

		<category><![CDATA[Social Networks]]></category>

		<guid isPermaLink="false">http://dancingmammoth.com/?p=119</guid>
		<description><![CDATA[You can now follow our exploits via Twitter, if you feel so inclined.
]]></description>
			<content:encoded><![CDATA[<p>You can now <a href="http://twitter.com/dancingmammoth">follow our exploits</a> via Twitter, if you feel so inclined.</p>
]]></content:encoded>
			<wfw:commentRss>http://dancingmammoth.com/2008/11/14/all-the-little-birds-on-jaybird-street-love-to-hear-the-mammoth-go-tweet-tweet-tweet/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Reason&#8217;s Giant Leap Into Video</title>
		<link>http://dancingmammoth.com/2008/11/14/reasons-giant-leap-into-video/</link>
		<comments>http://dancingmammoth.com/2008/11/14/reasons-giant-leap-into-video/#comments</comments>
		<pubDate>Fri, 14 Nov 2008 17:02:24 +0000</pubDate>
		<dc:creator>Matt Fetissoff</dc:creator>
		
		<category><![CDATA[Case Studies]]></category>

		<category><![CDATA[amazon s3]]></category>

		<category><![CDATA[design]]></category>

		<category><![CDATA[video]]></category>

		<guid isPermaLink="false">http://dancingmammoth.com/?p=68</guid>
		<description><![CDATA[In May of 2007, Reason.com asked Dancing Mammoth for help with a new endeavor: the launch of a website to serve as home for a series of short videos hosted by Drew Carey. In The Drew Carey Project, Drew would take to the street covering important current events and help people think about government in [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://reason.tv" target="_blank"><img class="alignright size-medium image" title="dot-tv-main2" src="http://dancingmammoth.com/wp-content/uploads/dot-tv-main2-318x270.jpg" alt="" width="318" height="270" /></a>In May of 2007, Reason.com asked Dancing Mammoth for help with a new endeavor: the launch of a website to serve as home for a series of short videos hosted by Drew Carey. In The Drew Carey Project, Drew would take to the street covering important current events and help people think about government in new ways.</p>
<p>We began by creating several mockups in Photoshop, utilizing some existing media to develop cohesive looking examples. With these, they were able to give us great feedback, helping to push the designs forward and moving closer to a design which met their needs.</p>
<p>A few color tweaks, a section or two added to the right column and the design was complete. Reliably serving up high quality video to a potentially massive visitor base was crucial, so we went with the Amazon S3 grid for this. So far this has been the perfect solution as well as an inexpensive one.</p>
<p>Currently, we are re-working the center column a bit to allow for smoother work flow, but the same basic feel will be retained.</p>
<h4>Some notes for the CSS geeks</h4>
<p>Notice how the text changes color on hover for the &#8220;send us your videos&#8221; and &#8220;Drew Carey Project Archive&#8221; areas in the right column? This was accomplished by using an &lt;a&gt; which has <a href="http://reason.tv/media/images/featured-hover-bg.gif">this</a> image applied to it using the background declaration. There&#8217;s a :hover state for the &lt;a&gt; which shifts the background image up by sixty eight pixels.</p>
<h4>Some earlier concepts:</h4>
<p><a class="thumbs" href="http://dancingmammoth.com/wp-content/uploads/dot-tv1lg.gif"><img class="alignnone size-full wp-image-82" title="dot-tv1" src="http://dancingmammoth.com/wp-content/uploads/dot-tv1.gif" alt="" /></a><a class="thumbs" href="http://dancingmammoth.com/wp-content/uploads/dot-tv2lg.gif"><img class="alignnone size-full wp-image-82" title="dot-tv1" src="http://dancingmammoth.com/wp-content/uploads/dot-tv2.gif" alt="" /></a><a class="thumbs" href="http://dancingmammoth.com/wp-content/uploads/dot-tv3lg.gif"><img class="alignnone size-full wp-image-82" title="dot-tv1" src="http://dancingmammoth.com/wp-content/uploads/dot-tv3.gif" alt="" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://dancingmammoth.com/2008/11/14/reasons-giant-leap-into-video/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Derived Attributes with UNION</title>
		<link>http://dancingmammoth.com/2008/08/10/derived-attributes-with-union/</link>
		<comments>http://dancingmammoth.com/2008/08/10/derived-attributes-with-union/#comments</comments>
		<pubDate>Sun, 10 Aug 2008 16:00:06 +0000</pubDate>
		<dc:creator>Francis Avila</dc:creator>
		
		<category><![CDATA[Lab]]></category>

		<category><![CDATA[derived attribute]]></category>

		<category><![CDATA[mysql]]></category>

		<category><![CDATA[optimization]]></category>

		<category><![CDATA[union]]></category>

		<category><![CDATA[view]]></category>

		<guid isPermaLink="false">http://dancingmammoth.com/?p=32</guid>
		<description><![CDATA[A Story
Recently, a client of ours wanted to institute a &#8220;point&#8221; system for an existing body of users. The idea was that certain actions of the user would generate points for that user, which the client could then track as part of an incentive program.
But What are &#8220;Points&#8221;?
At the time, we had a simple &#8220;users&#8221; [...]]]></description>
			<content:encoded><![CDATA[<h4>A Story</h4>
<p>Recently, a client of ours wanted to institute a &#8220;point&#8221; system for an existing body of users. The idea was that certain actions of the user would generate points for that user, which the client could then track as part of an incentive program.</p>
<h5>But What are &#8220;Points&#8221;?</h5>
<p>At the time, we had a simple &#8220;users&#8221; table in our database which stored all our user-related data. Now we were asked, essentially, to add a new &#8220;points&#8221; attribute to the &#8220;user&#8221; entity. However, we could not simply add a &#8220;points&#8221; column to the &#8220;user&#8221; table, because the client needed to track individual point-granting actions separately, with descriptions and such.</p>
<p>But this was also not a one-to-many relationship with an abstract &#8220;point-event&#8221; entity either, since some points were inferred from information which was properly normalized into other parts of the database. For example, referring another user (information we know at user registration time) was worth a certain number of points, but to copy a &#8220;referred user&#8221; event to a &#8220;point-event&#8221; entity would mean denormalizing the database.  If a user-referral were added or changed later, we would have to make sure to do the same thing to a corresponding point-event.</p>
<p>Thus a user&#8217;s &#8220;points&#8221; are an attribute of the user, but the value of this attribute is derived from potentially many different entities or attributes.  Guess what? It&#8217;s a <a href="http://it.toolbox.com/blogs/enterprise-solutions/understanding-attributes-in-er-diagrams-14287">derived attribute</a> (scroll to the bottom).</p>
<p>So, how are we going to deal with this?</p>
<h4>Implementation</h4>
<h5>Derived Columns</h5>
<p>Some &#8220;real&#8221; databases have native support for derived attributes (e.g., SQL Server) but as far as I know they all require that the value of the derived attribute be defined as an expression, not the result of an arbitrary query.  We could get around this using a stored function which calculates the points for us, but this particular database was MySQL (which does not support derived attributes), version 4.1 (which does not support stored functions).</p>
<p>In any case, this is a bad solution for us because any changes to the point calculation algorithm would require modification of the database, yet we had been accustomed to putting this kind of logic into the application.  Additionally, a lazy <code>SELECT *</code> (many of which were unfortunately sprinkled throughout our application) would suddenly become much more expensive, requiring an additional function call per row.</p>
<h5>Application Code</h5>
<p>The other solution, of course, is that we simply put all the point-calculation code into the application.  The problem with this is that it would take multiple queries to the database for every user that interested us, and we could potentially get the wrong point value if a change were made to the database in between our queries (since MySQL MyISAM does not have transactions).  Plus, if we want to sort by points (or something more complicated), we would have to do the sorting ourselves, in the application.</p>
<h5>UNION</h5>
<p>Clearly, we wanted to handle point calculation by a single query. The solution we finally hit upon was to use a temporary table (not a view, since MySQL 4.1 doesn&#8217;t support them) filled by a <code>UNION</code>. This is quite possibly the only good use for a <code>UNION</code>. Each subquery of the <code>UNION</code> would calculate points based on a particular attribute or entity, and all the subqueries would <code>SELECT</code> to common column names.</p>
<pre name="code" class="sql">
DROP TEMPORARY TABLE IF EXISTS tmp_all_points;
CREATE TEMPORARY TABLE tmp_all_points
-- Get referrer-derived points
(SELECT user.id AS user_id, COUNT(*)*5 AS points
FROM user ... INNER JOIN ... GROUP BY ...)
UNION
-- Get pointevents-derived points
(SELECT user_id AS user_id, SUM(points) AS points
FROM pointevents GROUP BY user_id HAVING points != 0);
</pre>
<p>This will give us a temporary table with 0, 1, or 2 rows per user. If we want to limit this to particular users, we can add the relevant <code>WHERE</code> conditions to the individual subqueries before we send them to the database.</p>
<p>Now if we want to do any queries which involve points, we can just treat <code>tmp_all_points</code> as a &#8220;points&#8221; entity with a many-to-one relationship with the &#8220;users&#8221; entity.</p>
<p>Want the top five point-holders?</p>
<pre name="code" class="sql">
SELECT users.name, SUM(tmp_all_points.points) AS points
FROM users
INNER JOIN tmp_all_points ON users.id = tmp_all_points.users_id
GROUP BY users.id
ORDER BY points DESC
LIMIT 5
</pre>
<h4>Happy Ending?</h4>
<p>By using a <code>UNION</code>, we were able to neatly model the derived attribute as a table, using a single query that maps easily to the logic of the derived attribute and is easy to extend to account for any additional criteria that the client may dream up.  And we didn&#8217;t have to denormalize our database or introduce complex application code.</p>
<p>There is a caveat, however.  Tables defined by a query have no index, and probably we are going to want to join on this table, which means we&#8217;ll be doing a join without an index.  For this reason, it is pretty important to keep the result set of your UNION query as small as possible using additional <code>WHERE</code> conditions.</p>
<p>If your result set will always be large, split off the temporary table creation into a definition with keys and use a <code>INSERT INTO tmp_table SELECT ... UNION SELECT ...</code>.  <strong>Don&#8217;t</strong> use <code>CREATE INDEX</code> after filling your table, since creating an index on a full table is <em>much</em> slower than building it incrementally (except for <code>FULLTEXT</code> indexes, where the opposite is true).</p>
<h5>Don&#8217;t Try This With Views</h5>
<p>If you are using MySQL 5.0 or above, you won&#8217;t be able to mitigate this problem by using a <a href="http://dev.mysql.com/doc/refman/5.0/en/create-view.html"><code>VIEW</code></a>.  MySQL is <a href="http://www.mysqlperformanceblog.com/2007/08/12/mysql-view-as-performance-troublemaker/">not very good at optimizing views</a>. If there is not a one-to-one relationship between the rows of your view and the rows of the underlying tables, MySQL will use <code>ALGORITHM = TEMPTABLE</code> for your view. So any view with a UNION in it will be created as a temporary table anyway.</p>
<p>Thus I would not wrap a <code>UNION</code> in a view for this technique, since you can&#8217;t control the result set size for a view and you will be generating a new temporary table every time you use the view, instead of once per connection.</p>
]]></content:encoded>
			<wfw:commentRss>http://dancingmammoth.com/2008/08/10/derived-attributes-with-union/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
