<?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>tail -f findings.out &#187; MySQL</title>
	<atom:link href="http://dancingpenguinsoflight.com/category/mysql/feed/" rel="self" type="application/rss+xml" />
	<link>http://dancingpenguinsoflight.com</link>
	<description></description>
	<lastBuildDate>Sun, 21 Aug 2011 14:33:34 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Troubleshooting MySQL queries: a useful workflow</title>
		<link>http://dancingpenguinsoflight.com/2010/12/troubleshooting-mysql-queries-a-useful-workflow/</link>
		<comments>http://dancingpenguinsoflight.com/2010/12/troubleshooting-mysql-queries-a-useful-workflow/#comments</comments>
		<pubDate>Mon, 13 Dec 2010 04:17:36 +0000</pubDate>
		<dc:creator>Samuel Huckins</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[DBA]]></category>
		<category><![CDATA[sysadmin]]></category>

		<guid isPermaLink="false">http://dancingpenguinsoflight.com/?p=1759</guid>
		<description><![CDATA[Configuring and optimizing MySQL servers, from the underlying hardware to the instance settings on up to the application queries, is a multi-faceted and complex process. Here I&#8217;d like to assume you&#8217;ve got a well-configured physical server (it&#8217;s at least functioning &#8230; <a href="http://dancingpenguinsoflight.com/2010/12/troubleshooting-mysql-queries-a-useful-workflow/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Configuring and optimizing MySQL servers, from the underlying hardware to the instance settings on up to the application queries, is a multi-faceted and complex process. Here I&#8217;d like to assume you&#8217;ve got a well-configured physical server (it&#8217;s at least functioning and not manifesting any obvious issues) and that you have some decent configuration settings in place. If you&#8217;re still facing what you think to be sub-optimal performance, I&#8217;m going to describe a workflow you might find useful in your investigations.<br />
<span id="more-1759"></span></p>
<h2>Find your targets: the slow query log</h2>
<p>First, make sure you have the <a target="_blank" title="Slow Query log docs" href="http://dev.mysql.com/doc/refman/5.1/en/slow-query-log.html">slow query log</a> turned on and properly configured. Here&#8217;s an example /etc/my.cnf section:</p>
<div class="codecolorer-container sql blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"># Slow query log settings<br />
# Enable slow log<br />
slow_query_log<span style="color: #66cc66;">=</span><span style="color: #cc66cc;">1</span><br />
# Slow query logfile will be LOGDIR<span style="color: #66cc66;">/</span>mysql<span style="color: #66cc66;">-</span>slow<span style="color: #66cc66;">.</span>log<span style="color: #66cc66;">.</span> <br />
# <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #993333; font-weight: bold;">IS</span> host_name<span style="color: #66cc66;">-</span>slow<span style="color: #66cc66;">.</span>log<br />
slow_query_log_file<span style="color: #66cc66;">=</span>mysql<span style="color: #66cc66;">-</span>slow<span style="color: #66cc66;">.</span>log<br />
# Queries taking <span style="color: #cc66cc;">5</span> seconds <span style="color: #993333; font-weight: bold;">OR</span> longer will be captured<br />
long_query_time<span style="color: #66cc66;">=</span><span style="color: #cc66cc;">5</span></div></td></tr></tbody></table></div>
<p>Add this to your current configuration (or edit as necessary) and restart the MySQL server. The slow query log adds no overhead and is very useful in finding what queries are taking how long on your system.</p>
<h2>mysqlsla: slow query log analysis</h2>
<p><a target="_blank" title="mysqla home" href="http://hackmysql.com/mysqlsla">mysqlsla</a> can parse and analyze all manner of MySQL logs. In this case, let&#8217;s use it to analyze our slow query log, assuming the server has been running for a bit to collect an acceptable sample of slow queries. One day to a week should be sufficient, depending on your usage patterns.</p>
<p>Download, made executable, run:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #c20cb9; font-weight: bold;">wget</span> http:<span style="color: #000000; font-weight: bold;">//</span>hackmysql.com<span style="color: #000000; font-weight: bold;">/</span>scripts<span style="color: #000000; font-weight: bold;">/</span>mysqlsla<br />
<span style="color: #c20cb9; font-weight: bold;">chmod</span> u+x mysqlsla<br />
.<span style="color: #000000; font-weight: bold;">/</span>mysqlsla <span style="color: #660033;">--log-type</span>=slow <span style="color: #000000; font-weight: bold;">/</span>path<span style="color: #000000; font-weight: bold;">/</span>to<span style="color: #000000; font-weight: bold;">/</span>slow<span style="color: #000000; font-weight: bold;">/</span>log <span style="color: #000000; font-weight: bold;">&gt;</span> mysqlsla-report.txt</div></td></tr></tbody></table></div>
<p>You minimally need to specify the path to your slow query log and indicate the type of log you are analyzing. Additional options are available for you to specify what in the log to analyze including the specific database and the type of query used. See <a target="_blank" title="mysqlsla docs" href="http://hackmysql.com/mysqlsla_documentation">the documentation</a>. </p>
<p>What you&#8217;ll get out is a nicely formatted informative report of the queries found in the slow query log, sorted by what took the longest. You will see how much time was spent in a locked state, how many rows were sent and examined, what users were involved, the query itself, and an abstracted form of the query with particular parameter values generalized:</p>
<p><a href="http://dancingpenguinsoflight.com/wp-content/uploads/2010/12/mysqlsla.png"><img src="http://dancingpenguinsoflight.com/wp-content/uploads/2010/12/mysqlsla.png" alt="" title="mysqlsla" width="780" height="469" class="aligncenter size-full wp-image-1768" /></a></p>
<p>Looking through this report will allow you to get a sense of what queries are taking up the most of your instance&#8217;s time (and are therefore your best points to focus on).</p>
<h2>Analyzing target queries with the Query Profiler</h2>
<p>I discuss the basics of the MySQL Query Profiler <a target="_blank" title="Post on the MySQL Query Profiler" href="http://dancingpenguinsoflight.com/2010/12/debugging-bottlenecks-with-the-mysql-query-profiler/">in this post</a>. Let&#8217;s assume you&#8217;ve found a few queries using mysqlsla as shown above that you want to learn more about and optimize. You could wrap them in a file like so:</p>
<div class="codecolorer-container sql blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"># MySQL Query Profile script<br />
# profile<span style="color: #66cc66;">.</span><span style="color: #993333; font-weight: bold;">SQL</span><br />
<span style="color: #993333; font-weight: bold;">SET</span> @@profiling<span style="color: #66cc66;">=</span><span style="color: #cc66cc;">1</span>;<br />
# Buffer <br />
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">&quot;ignore&quot;</span> <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">&quot;START&quot;</span>;<br />
# Problem query one:<br />
<span style="color: #993333; font-weight: bold;">SELECT</span> foo<span style="color: #66cc66;">,</span> bar <span style="color: #993333; font-weight: bold;">FROM</span> mydb<span style="color: #66cc66;">.</span>mytable;<br />
# Problem query two:<br />
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #993333; font-weight: bold;">COUNT</span><span style="color: #66cc66;">&#40;</span>foo<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">FROM</span> mydb<span style="color: #66cc66;">.</span>mytable<br />
<span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> bar;<br />
# Buffer <br />
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">&quot;ignore&quot;</span> <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">&quot;END&quot;</span>;<br />
<span style="color: #993333; font-weight: bold;">SHOW</span> profile <span style="color: #993333; font-weight: bold;">FOR</span> query <span style="color: #cc66cc;">1</span>;<br />
<span style="color: #993333; font-weight: bold;">SHOW</span> profile <span style="color: #993333; font-weight: bold;">FOR</span> query <span style="color: #cc66cc;">2</span>;</div></td></tr></tbody></table></div>
<p>And run this wrapper script as:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">mysql <span style="color: #660033;">-u</span> root <span style="color: #660033;">-pXXX</span> <span style="color: #000000; font-weight: bold;">&lt;</span> profile.sql <span style="color: #000000; font-weight: bold;">&gt;</span> profile-results.txt</div></td></tr></tbody></table></div>
<p>The buffer queries give you markers in the output to jump to if you want to filter out the actual data results from your output file (since you&#8217;re probably just concerned with the profile data at this point, having a well-defined query). I&#8217;ll leave it to the reader to come up with an improved command to remove the query output from the file generated, producing a CSV for each report. (Add to the comments if you make this please <img src='http://dancingpenguinsoflight.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> )</p>
<p>So to zoom in on the most problematic queries we just need to:</p>
<ul>
<li>Enable the slow query log</li>
<li>Process representative slow query log entries with mysqlsla</li>
<li>Analyze most troublesome queries with the MySQL Query Profiler</li>
</ul>
    ]]></content:encoded>
			<wfw:commentRss>http://dancingpenguinsoflight.com/2010/12/troubleshooting-mysql-queries-a-useful-workflow/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Debugging bottlenecks with the MySQL Query Profiler</title>
		<link>http://dancingpenguinsoflight.com/2010/12/debugging-bottlenecks-with-the-mysql-query-profiler/</link>
		<comments>http://dancingpenguinsoflight.com/2010/12/debugging-bottlenecks-with-the-mysql-query-profiler/#comments</comments>
		<pubDate>Mon, 13 Dec 2010 02:00:04 +0000</pubDate>
		<dc:creator>Samuel Huckins</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[DBA]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://dancingpenguinsoflight.com/?p=1732</guid>
		<description><![CDATA[I was throughly pleased to discover the MySQL Query Profiler facility recently. Somehow I hadn&#8217;t heard about it (or recalled anyway) until now. In short it provides a very easy way to view how much time (down to the microsecond) &#8230; <a href="http://dancingpenguinsoflight.com/2010/12/debugging-bottlenecks-with-the-mysql-query-profiler/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I was throughly pleased to discover the MySQL Query Profiler facility recently. Somehow I hadn&#8217;t heard about it (or recalled anyway) until now. In short it provides a very easy way to view how much time (down to the microsecond) a query takes as it goes through each step from request to the return of data. You can quickly spot whether the bottleneck making that one query so slow is that it has to write a temp table to disk or that an overly large and unused dataset has to be sorted. This is quite a timesaver for many situations, and it&#8217;s an amazingly handy tool to have around. If you&#8217;ve been a bit uncertain trying to optimize from the results of EXPLAIN, this is especially a great tool to try.<br />
<span id="more-1732"></span><br />
If you&#8217;re running MySQL server version 5.0.37 or higher this is available by default.  For older versions of MySQL you have to go through <a target="_blank" title="Enabling Profiler for older MySQL versions" href="http://forge.mysql.com/wiki/Show_Profiles_-_testing_under_5_1">various steps</a> to enable it. Let&#8217;s test it out (if you need a quick test DB to mess with, read <a target="_blank" title="Quickly setup test DB" href="http://dancingpenguinsoflight.com/2009/09/rapidly-set-up-a-mysql-database-for-testing/">this post</a>).</p>
<p>Toggling Profiling on and off is a matter of setting a session variable, aptly named &#8216;<a target="_blank" title="Info on profiling variable" href="http://dev.mysql.com/doc/refman/5.0/en/server-system-variables.html#sysvar_profiling">profiling</a>&#8216;. Here&#8217;s how to set and read it:</p>
<div class="codecolorer-container sql blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">mysql<span style="color: #66cc66;">&gt;</span> <span style="color: #993333; font-weight: bold;">SET</span> @@profiling <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span>;<br />
mysql<span style="color: #66cc66;">&gt;</span> <span style="color: #993333; font-weight: bold;">SELECT</span> @@profiling;</div></td></tr></tbody></table></div>
<p>Once on, subsequent queries you run will have profiling information collected about them. By default the last 15 queries&#8217; profiling information is kept, but you can increase this up to 100 by setting profiling_history_size. To view the profiles collected so far just run <a target="_blank" title="MySQL manual page for SHOW PROFILES" href="http://dev.mysql.com/doc/refman/5.1/en/show-profiles.html">SHOW PROFILES</a>:</p>
<p><a href="http://dancingpenguinsoflight.com/wp-content/uploads/2010/12/show-profiles.png"><img src="http://dancingpenguinsoflight.com/wp-content/uploads/2010/12/show-profiles.png" alt="" title="show-profiles" width="651" height="303" class="aligncenter size-full wp-image-1740" /></a></p>
<p>The queries are identified in sequence of when they were run. You can view how long they took as well as the query itself. Once you select the one you want to get information on, the simplest way to get it is a variant of the SHOW PROFILE command:</p>
<p><a href="http://dancingpenguinsoflight.com/wp-content/uploads/2010/12/profile-example.png"><img src="http://dancingpenguinsoflight.com/wp-content/uploads/2010/12/profile-example.png" alt="" title="profile-example" width="364" height="395" class="aligncenter size-full wp-image-1741" /></a></p>
<p>This describes every step of the process from checking the query cache to returning the result and cleaning up with the duration for each step. Awesome! You can also dive into more particular data by passing a type parameter after PROFILE, such as swap and cpu. I&#8217;ve had mixed results with those, so I&#8217;ll wait until I learn more. Info <a target="_blank" title="MySQL manual page for SHOW PROFILES" href="http://dev.mysql.com/doc/refman/5.1/en/show-profiles.html">in the docs</a> if you want to give it a try.</p>
<p><strong><em>Note of caution</em></strong>: If you show the profiling information for a more complicated query you might get a LOT of output. If, for example, each row in your resultset required touching a view, you might start to get hundreds or thousands of lines. This can be a little disconcerting when it first happens. After it has stopped or you kill it, check out the <a target="_blank" title="MySQL docs on information_schema.profiling" href="http://dev.mysql.com/doc/refman/5.1/en/profiling-table.html">information_schema.profiling table</a> and manually pull the information you need. <a target="_blank" title="SQL Query Profiler" href="http://dev.mysql.com/tech-resources/articles/using-new-query-profiler.html">This helpful article</a> provides an example (about halfway through) where aggregation functions were used on this information_schema table to provide the information you&#8217;re likely looking for.</p>
<p>For another example of an application of the Query Profiler, check out <a target="_blank" title="Query Cache effectiveness" href="http://ronaldbradford.com/blog/mysql-query-cache-path-2009-09-28/">this post</a> demonstrating the effectiveness of the query cache. That same article also provides an example of using the Query Profiler to show what MySQL source functions are being called as well, very interesting!</p>
    ]]></content:encoded>
			<wfw:commentRss>http://dancingpenguinsoflight.com/2010/12/debugging-bottlenecks-with-the-mysql-query-profiler/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Tune MySQL like a pro with MySQLTuner</title>
		<link>http://dancingpenguinsoflight.com/2010/03/tune-mysql-like-a-pro-with-mysqltuner/</link>
		<comments>http://dancingpenguinsoflight.com/2010/03/tune-mysql-like-a-pro-with-mysqltuner/#comments</comments>
		<pubDate>Sat, 13 Mar 2010 23:22:10 +0000</pubDate>
		<dc:creator>Samuel Huckins</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[CLI]]></category>
		<category><![CDATA[efficiency]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://dancingpenguinsoflight.com/?p=1447</guid>
		<description><![CDATA[I came across MySQLTuner recently and was most pleasantly surprised. It&#8217;s a Perl script that only requires your MySQL user and password to provide detailed and useful checks of a running MySQL instance. First though, check out the awesome URL &#8230; <a href="http://dancingpenguinsoflight.com/2010/03/tune-mysql-like-a-pro-with-mysqltuner/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I came across <a title="MySQLTuner blog" target="_blank" href="http://blog.mysqltuner.com/">MySQLTuner</a> recently and was most pleasantly surprised. It&#8217;s a Perl script that only requires your MySQL user and password to provide detailed and useful checks of a running MySQL instance. First though, check out the awesome URL you <a title="MySQLTuner download" target="_blank" href="http://blog.mysqltuner.com/download/">download it</a> at:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #c20cb9; font-weight: bold;">wget</span> mysqltuner.pl</div></td></tr></tbody></table></div>
<p>Yeah, that&#8217;s the actual URL that works. Pretty sweet.</p>
<p>Anyway, next you make it executable, run it, enter creds:</p>
<p><img src="http://dancingpenguinsoflight.com/wp-content/uploads/2010/03/Screenshot1.png" alt="Get MySQLTuner running" title="MySQLTuner_first-steps" width="613" height="414" class="size-full wp-image-1452" /></p>
<p>Then the goodies appear:</p>
<p><img src="http://dancingpenguinsoflight.com/wp-content/uploads/2010/03/results.png" alt="MySQLTuner Results" title="MySQLTuner_results" width="640" height="630" class="size-full wp-image-1449" /></p>
<p>Oh, that query_cache_limit is tiny! At this point, no changes have been made to your setup. But at a glance you get helpful stats, validate that changes you&#8217;ve decided to make are in place, and get alerted to potential improvements.</p>
    ]]></content:encoded>
			<wfw:commentRss>http://dancingpenguinsoflight.com/2010/03/tune-mysql-like-a-pro-with-mysqltuner/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Better access to MySQL create view statements</title>
		<link>http://dancingpenguinsoflight.com/2009/11/better-access-to-mysql-create-view-statements/</link>
		<comments>http://dancingpenguinsoflight.com/2009/11/better-access-to-mysql-create-view-statements/#comments</comments>
		<pubDate>Mon, 16 Nov 2009 04:23:29 +0000</pubDate>
		<dc:creator>Samuel Huckins</dc:creator>
				<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://dancingpenguinsoflight.com/?p=1066</guid>
		<description><![CDATA[I&#8217;ve found that I often create several views that are variations on an initial one, providing a slightly different convenient slice of the data as the need arises. But when a view is created the syntax actually stored can be &#8230; <a href="http://dancingpenguinsoflight.com/2009/11/better-access-to-mysql-create-view-statements/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve found that I often create several views that are variations on an initial one, providing a slightly different convenient slice of the data as the need arises. But when a view is created the syntax actually stored can be quite different than what you put in. The parser reorganizes and rewrites to make everything explicit. While better for performance in running the view, this has the unfortunate side effect of transmuting a once readable statement into a forest of parentheses and backticks that can and does induce tears.</p>
<p>First an example view that I created using the <a title="Post on quickly setting up the test world database" target="_blank" href="http://dancingpenguinsoflight.com/2009/09/rapidly-set-up-a-mysql-database-for-testing/">handy world database</a>:</p>
<div class="codecolorer-container sql blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">VIEW</span> world<span style="color: #66cc66;">.</span>low_central_luzon <span style="color: #993333; font-weight: bold;">AS</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span> a<span style="color: #66cc66;">.</span>Name <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">&quot;City&quot;</span><span style="color: #66cc66;">,</span> b<span style="color: #66cc66;">.</span>Name <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">&quot;Country&quot;</span><span style="color: #66cc66;">,</span> a<span style="color: #66cc66;">.</span>Population<span style="color: #66cc66;">,</span> a<span style="color: #66cc66;">.</span>District <br />
<span style="color: #993333; font-weight: bold;">FROM</span> world<span style="color: #66cc66;">.</span>City a<br />
<span style="color: #993333; font-weight: bold;">JOIN</span> world<span style="color: #66cc66;">.</span>Country b <span style="color: #993333; font-weight: bold;">ON</span> <span style="color: #66cc66;">&#40;</span>a<span style="color: #66cc66;">.</span>CountryCode <span style="color: #66cc66;">=</span> b<span style="color: #66cc66;">.</span>Code<span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">WHERE</span> b<span style="color: #66cc66;">.</span>Continent <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;Asia&quot;</span><br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">AND</span> a<span style="color: #66cc66;">.</span>District <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;Central Luzon&quot;</span><br />
<span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> a<span style="color: #66cc66;">.</span>Population<br />
<span style="color: #993333; font-weight: bold;">LIMIT</span> <span style="color: #cc66cc;">10</span>;</div></td></tr></tbody></table></div>
<p>This is a view of the 10 cites with the lowest population in the Central Luzon region of Asia. Now let&#8217;s see what actually got stored. To get a view&#8217;s create statement you can use the MySQL Query Browser and right click the view name shown in the right under Schemata, selecting &#8220;Copy SQL to Clipboard&#8221;. Or you can run a query like:</p>
<div class="codecolorer-container sql blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">SELECT</span> VIEW_DEFINITION <span style="color: #993333; font-weight: bold;">FROM</span> information_schema<span style="color: #66cc66;">.</span>VIEWS<br />
<span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #993333; font-weight: bold;">TABLE_NAME</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;low_central_luzon&quot;</span><br />
<span style="color: #993333; font-weight: bold;">AND</span> TABLE_SCHEMA <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;world&quot;</span>;</div></td></tr></tbody></table></div>
<p>Here&#8217;s the result for the view above:</p>
<div class="codecolorer-container sql blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">`a`</span><span style="color: #66cc66;">.</span><span style="color: #ff0000;">`Name`</span> <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">`City`</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">`b`</span><span style="color: #66cc66;">.</span><span style="color: #ff0000;">`Name`</span> <br />
<span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">`Country`</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">`a`</span><span style="color: #66cc66;">.</span><span style="color: #ff0000;">`Population`</span> <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">`Population`</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">`a`</span><span style="color: #66cc66;">.</span><span style="color: #ff0000;">`District`</span> <br />
<span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #ff0000;">`District`</span> <span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`world`</span><span style="color: #66cc66;">.</span><span style="color: #ff0000;">`City`</span> <span style="color: #ff0000;">`a`</span> <span style="color: #993333; font-weight: bold;">JOIN</span> <span style="color: #ff0000;">`world`</span><span style="color: #66cc66;">.</span><span style="color: #ff0000;">`Country`</span> <span style="color: #ff0000;">`b`</span> <br />
<span style="color: #993333; font-weight: bold;">ON</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`a`</span><span style="color: #66cc66;">.</span><span style="color: #ff0000;">`CountryCode`</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">`b`</span><span style="color: #66cc66;">.</span><span style="color: #ff0000;">`Code`</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`b`</span><span style="color: #66cc66;">.</span><span style="color: #ff0000;">`Continent`</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Asia'</span><span style="color: #66cc66;">&#41;</span> <br />
<span style="color: #993333; font-weight: bold;">AND</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`a`</span><span style="color: #66cc66;">.</span><span style="color: #ff0000;">`District`</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Central Luzon'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> <span style="color: #ff0000;">`a`</span><span style="color: #66cc66;">.</span><span style="color: #ff0000;">`Population`</span> <span style="color: #993333; font-weight: bold;">LIMIT</span> <span style="color: #cc66cc;">10</span></div></td></tr></tbody></table></div>
<p>I added the line breaks for a modicum of readablilty, the statement is stored without them. I sure don&#8217;t want to edit that version in making a variant! This example isn&#8217;t actually too bad, but for real world complicated views, it really is quite difficult to read views exported in this way. I often try to store the original create view query just to avoid this pain. But sometimes I only have the stored syntax.</p>
<p>I&#8217;ve created a Bash function to make this whole process less painful:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">function</span> mysqldump_view <span style="color: #7a0874; font-weight: bold;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># Grabs the create statement for the view passed in the db passed.</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># Performs some text cleanup to make it more human readable, outputs</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># to file.</span><br />
&nbsp; &nbsp; <span style="color: #007800;">USAGE</span>=<span style="color: #ff0000;">&quot;USAGE: mysqldump_view DATABASE_NAME VIEW_NAME&quot;</span><br />
&nbsp; &nbsp; <span style="color: #007800;">opt_err</span>=<span style="color: #ff0000;">&quot;Must pass db and view.&quot;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$#</span> <span style="color: #660033;">-ne</span> <span style="color: #000000;">2</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #007800;">$opt_err</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #007800;">$USAGE</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">return</span> <span style="color: #000000;">1</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">fi</span><br />
&nbsp; &nbsp; <span style="color: #007800;">DB</span>=<span style="color: #007800;">$1</span><br />
&nbsp; &nbsp; <span style="color: #007800;">VIEW</span>=<span style="color: #007800;">$2</span><br />
&nbsp; &nbsp; <span style="color: #007800;">DEFAULT_USER</span>=<span style="color: #ff0000;">&quot;root&quot;</span><br />
&nbsp; &nbsp; <span style="color: #007800;">OUTPUT_FILE</span>=<span style="color: #ff0000;">&quot;view-<span style="color: #007800;">$VIEW</span>.sql&quot;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Attempting to connect with mysql defaults, user <span style="color: #007800;">$DEFAULT_USER</span>...&quot;</span><br />
mysql <span style="color: #660033;">-u</span> <span style="color: #007800;">$DEFAULT_USER</span> <span style="color: #660033;">-p</span> <span style="color: #660033;">--skip-column-names</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">&quot;SELECT VIEW_DEFINITION FROM <span style="color: #000099; font-weight: bold;">\<br />
</span>information_schema.VIEWS where TABLE_NAME = <span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">$VIEW</span><span style="color: #000099; font-weight: bold;">\&quot;</span> and TABLE_SCHEMA = <span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">$DB</span><span style="color: #000099; font-weight: bold;">\&quot;</span>;&quot;</span> \<br />
<span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">&quot;1s/^\(.*\)$/CREATE VIEW <span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">$VIEW</span><span style="color: #000099; font-weight: bold;">\&quot;</span> as<span style="color: #000099; font-weight: bold;">\n</span>\1/&quot;</span> \<br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/`,`/`,\n`/g'</span> \<br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/ from /\nfrom /g'</span> \<br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/ join /\n\tjoin /g'</span> \<br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/ where /\nwhere /g'</span> \<br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/ and /\n\tand /g'</span> \<br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/ limit /\nlimit /g'</span> \<br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/ order /\norder /g'</span> \<br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'$s/$/;/'</span> <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #007800;">$OUTPUT_FILE</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Done. View syntax written to <span style="color: #007800;">$OUTPUT_FILE</span>.&quot;</span><br />
&nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">return</span> <span style="color: #000000;">0</span><br />
<span style="color: #7a0874; font-weight: bold;">&#125;</span></div></td></tr></tbody></table></div>
<p>Now to get a cleaned up view you can call this function followed by the database and view names:<br />
<img src="http://dancingpenguinsoflight.com/wp-content/uploads/2009/11/example.png" alt="example" title="example" width="580" height="271" class="aligncenter size-full wp-image-1348" /></p>
<p>To get the create statements for multiple views you can <a target="_blank" title="Post on Bash loops" href="http://dancingpenguinsoflight.com/2007/10/loops-in-cli-warm-and-fuzzy/">use a loop</a>. For example:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">for</span> VIEW <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #ff0000;">&quot;high_central_luzon&quot;</span> <span style="color: #ff0000;">&quot;low_central_luzon&quot;</span>; <span style="color: #000000; font-weight: bold;">do</span> mysqldump_view world <span style="color: #007800;">$VIEW</span>; <span style="color: #000000; font-weight: bold;">done</span></div></td></tr></tbody></table></div>
<p>If you need some more flexibility than this I implemented it in Python after an initial fit of rage caused by trying to get various levels of nested strings properly escaped in Bash. That ended up being overly long and unnecessary, and a cooler head prevailed. But <a target="_blank" title="mysqldump_view.py on shuckins' github" href="http://github.com/shuckins/sph_code/blob/master/sysadmin/mysql/mysqldump_view.py">the script</a> is here on GitHub if you want it. It creates the same file although without using sed and with some error handling.</p>
    ]]></content:encoded>
			<wfw:commentRss>http://dancingpenguinsoflight.com/2009/11/better-access-to-mysql-create-view-statements/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Advanced ordering of MySQL results</title>
		<link>http://dancingpenguinsoflight.com/2009/09/advanced-ordering-of-mysql-results/</link>
		<comments>http://dancingpenguinsoflight.com/2009/09/advanced-ordering-of-mysql-results/#comments</comments>
		<pubDate>Mon, 07 Sep 2009 17:56:23 +0000</pubDate>
		<dc:creator>Samuel Huckins</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://dancingpenguinsoflight.com/?p=796</guid>
		<description><![CDATA[MySQL&#8217;s &#8220;order by&#8221; keyword allows the order in which result rows are returned to be defined. This is quite useful in a wide variety of circumstances. You can specify any number of columns whose values you want to order the &#8230; <a href="http://dancingpenguinsoflight.com/2009/09/advanced-ordering-of-mysql-results/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a target="_blank" title="Sorting rows in MySQL" href="http://dev.mysql.com/doc/refman/5.1/en/sorting-rows.html">MySQL&#8217;s &#8220;order by&#8221; keyword</a> allows the order in which result rows are returned to be defined. This is quite useful in a wide variety of circumstances. You can specify any number of columns whose values you want to order the results by, as well as what sorting order to use (desc or asc; asc is default). However, you may also run into situations in which you want certain groups within the resultset displayed in a certain order based on particular values in the results, not just according to alphanumeric sorting. This is easy to achieve by use of the equal operator or the <a target="_blank" title="field keyword in MySQL" href="http://dev.mysql.com/doc/refman/5.1/en/string-functions.html#function_field">field keyword</a> within the order by clause. </p>
<p>Some examples are in order. I&#8217;ll be using <a target="_blank" title="Article on using the world DB" href="http://dancingpenguinsoflight.com/2009/09/rapidly-set-up-a-mysql-database-for-testing/">the world database</a>. The following shows country names and a language spoken therein for European countries that speak Arabic, Dutch, and/or Greek:</p>
<div class="codecolorer-container sql blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">SELECT</span> a<span style="color: #66cc66;">.</span>Name<span style="color: #66cc66;">,</span> b<span style="color: #66cc66;">.</span><span style="color: #993333; font-weight: bold;">LANGUAGE</span> <span style="color: #993333; font-weight: bold;">FROM</span> Country a<br />
<span style="color: #993333; font-weight: bold;">JOIN</span> CountryLanguage b <span style="color: #993333; font-weight: bold;">ON</span> <span style="color: #66cc66;">&#40;</span>a<span style="color: #66cc66;">.</span>Code <span style="color: #66cc66;">=</span> b<span style="color: #66cc66;">.</span>CountryCode<span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">WHERE</span> a<span style="color: #66cc66;">.</span>Continent <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;Europe&quot;</span><br />
<span style="color: #993333; font-weight: bold;">AND</span> b<span style="color: #66cc66;">.</span><span style="color: #993333; font-weight: bold;">LANGUAGE</span> <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;Arabic&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;Dutch&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;Greek&quot;</span><span style="color: #66cc66;">&#41;</span>;</div></td></tr></tbody></table></div>
<p>This returns:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">+-------------+----------+<br />
| Name &nbsp; &nbsp; &nbsp; &nbsp;| Language |<br />
+-------------+----------+<br />
| Netherlands | Arabic &nbsp; |<br />
| Netherlands | Dutch &nbsp; &nbsp;|<br />
| Albania &nbsp; &nbsp; | Greek &nbsp; &nbsp;|<br />
| Belgium &nbsp; &nbsp; | Arabic &nbsp; |<br />
| Belgium &nbsp; &nbsp; | Dutch &nbsp; &nbsp;|<br />
| Gibraltar &nbsp; | Arabic &nbsp; |<br />
| Greece &nbsp; &nbsp; &nbsp;| Greek &nbsp; &nbsp;|<br />
| France &nbsp; &nbsp; &nbsp;| Arabic &nbsp; |<br />
| Sweden &nbsp; &nbsp; &nbsp;| Arabic &nbsp; |<br />
| Germany &nbsp; &nbsp; | Greek &nbsp; &nbsp;|<br />
| Denmark &nbsp; &nbsp; | Arabic &nbsp; |<br />
+-------------+----------+</div></td></tr></tbody></table></div>
<p>But what if we want Dutch speaking countries first? We can&#8217;t use order by Language desc or asc since Dutch results are in the middle of either sorting. Instead:</p>
<div class="codecolorer-container sql blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">SELECT</span> a<span style="color: #66cc66;">.</span>Name<span style="color: #66cc66;">,</span> b<span style="color: #66cc66;">.</span><span style="color: #993333; font-weight: bold;">LANGUAGE</span> <span style="color: #993333; font-weight: bold;">FROM</span> Country a<br />
<span style="color: #993333; font-weight: bold;">JOIN</span> CountryLanguage b <span style="color: #993333; font-weight: bold;">ON</span> <span style="color: #66cc66;">&#40;</span>a<span style="color: #66cc66;">.</span>Code <span style="color: #66cc66;">=</span> b<span style="color: #66cc66;">.</span>CountryCode<span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">WHERE</span> a<span style="color: #66cc66;">.</span>Continent <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;Europe&quot;</span><br />
<span style="color: #993333; font-weight: bold;">AND</span> b<span style="color: #66cc66;">.</span><span style="color: #993333; font-weight: bold;">LANGUAGE</span> <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;Arabic&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;Dutch&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;Greek&quot;</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> <span style="color: #993333; font-weight: bold;">LANGUAGE</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Dutch&quot;</span> <span style="color: #993333; font-weight: bold;">DESC</span><span style="color: #66cc66;">,</span> <span style="color: #993333; font-weight: bold;">LANGUAGE</span>;</div></td></tr></tbody></table></div>
<p>This orders the results with records having Language = &#8220;Dutch&#8221; first, followed by all the others ordered by their Language value. And this is the desired result:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">+-------------+----------+<br />
| Name &nbsp; &nbsp; &nbsp; &nbsp;| Language |<br />
+-------------+----------+<br />
| Netherlands | Dutch &nbsp; &nbsp;|<br />
| Belgium &nbsp; &nbsp; | Dutch &nbsp; &nbsp;|<br />
| France &nbsp; &nbsp; &nbsp;| Arabic &nbsp; |<br />
| Gibraltar &nbsp; | Arabic &nbsp; |<br />
| Netherlands | Arabic &nbsp; |<br />
| Denmark &nbsp; &nbsp; | Arabic &nbsp; |<br />
| Belgium &nbsp; &nbsp; | Arabic &nbsp; |<br />
| Sweden &nbsp; &nbsp; &nbsp;| Arabic &nbsp; |<br />
| Albania &nbsp; &nbsp; | Greek &nbsp; &nbsp;|<br />
| Germany &nbsp; &nbsp; | Greek &nbsp; &nbsp;|<br />
| Greece &nbsp; &nbsp; &nbsp;| Greek &nbsp; &nbsp;|<br />
+-------------+----------+</div></td></tr></tbody></table></div>
<p>You can specify as many values in the order by clause as you want, each also allowing an asc or desc modifier. If you have a number of values in one field you want to specify, the field keyword can save you some typing:</p>
<div class="codecolorer-container sql blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">SELECT</span> a<span style="color: #66cc66;">.</span>Name<span style="color: #66cc66;">,</span> b<span style="color: #66cc66;">.</span><span style="color: #993333; font-weight: bold;">LANGUAGE</span> <span style="color: #993333; font-weight: bold;">FROM</span> Country a<br />
<span style="color: #993333; font-weight: bold;">JOIN</span> CountryLanguage b <span style="color: #993333; font-weight: bold;">ON</span> <span style="color: #66cc66;">&#40;</span>a<span style="color: #66cc66;">.</span>Code <span style="color: #66cc66;">=</span> b<span style="color: #66cc66;">.</span>CountryCode<span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">WHERE</span> a<span style="color: #66cc66;">.</span>Continent <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;Europe&quot;</span><br />
<span style="color: #993333; font-weight: bold;">AND</span> b<span style="color: #66cc66;">.</span><span style="color: #993333; font-weight: bold;">LANGUAGE</span> <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;Arabic&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;Dutch&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;Greek&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;Fries&quot;</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> <span style="color: #993333; font-weight: bold;">FIELD</span><span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">LANGUAGE</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;Greek&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;Dutch&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;Fries&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;Arabic&quot;</span><span style="color: #66cc66;">&#41;</span>;</div></td></tr></tbody></table></div>
<p>Returning the customized ordering:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">+-------------+----------+<br />
| Name &nbsp; &nbsp; &nbsp; &nbsp;| Language |<br />
+-------------+----------+<br />
| Albania &nbsp; &nbsp; | Greek &nbsp; &nbsp;|<br />
| Germany &nbsp; &nbsp; | Greek &nbsp; &nbsp;|<br />
| Greece &nbsp; &nbsp; &nbsp;| Greek &nbsp; &nbsp;|<br />
| Netherlands | Dutch &nbsp; &nbsp;|<br />
| Belgium &nbsp; &nbsp; | Dutch &nbsp; &nbsp;|<br />
| Netherlands | Fries &nbsp; &nbsp;|<br />
| Belgium &nbsp; &nbsp; | Arabic &nbsp; |<br />
| Gibraltar &nbsp; | Arabic &nbsp; |<br />
| France &nbsp; &nbsp; &nbsp;| Arabic &nbsp; |<br />
| Netherlands | Arabic &nbsp; |<br />
| Denmark &nbsp; &nbsp; | Arabic &nbsp; |<br />
| Sweden &nbsp; &nbsp; &nbsp;| Arabic &nbsp; |<br />
+-------------+----------+</div></td></tr></tbody></table></div>
    ]]></content:encoded>
			<wfw:commentRss>http://dancingpenguinsoflight.com/2009/09/advanced-ordering-of-mysql-results/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rapidly set up a MySQL database for testing</title>
		<link>http://dancingpenguinsoflight.com/2009/09/rapidly-set-up-a-mysql-database-for-testing/</link>
		<comments>http://dancingpenguinsoflight.com/2009/09/rapidly-set-up-a-mysql-database-for-testing/#comments</comments>
		<pubDate>Mon, 07 Sep 2009 16:52:19 +0000</pubDate>
		<dc:creator>Samuel Huckins</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[efficiency]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://dancingpenguinsoflight.com/?p=1170</guid>
		<description><![CDATA[Sometimes you just want a database to run some queries against. Any reasonable set of tables with data pertaining to something not terribly complicated will do. Perhaps you have an urge to tease out the intricacies of correlated subqueries, or &#8230; <a href="http://dancingpenguinsoflight.com/2009/09/rapidly-set-up-a-mysql-database-for-testing/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Sometimes you just want a database to run some queries against. Any reasonable set of tables with data pertaining to something not terribly complicated will do. Perhaps you have an urge to tease out the intricacies of correlated subqueries, or you need to test some complicated pattern matching functions. MySQL provides a database dump for such recreation, called &#8220;world&#8221;. The <a target="_blank" title="On MySQL world database" href="http://dev.mysql.com/doc/world-setup/en/world-setup.html">world database</a> contains global population data from <a target="_blank" title="World in Figures" href="http://www.stat.fi/tup/maanum/index_en.html">Statistics Finland</a>. The data itself is several years old, but it works fine as general test fodder.</p>
<p>Since I normally only use it on my own machines for testing, I&#8217;ve found setting it up to be a fixed process. So I created this alias for such situations:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">setup_world_db</span>=<span style="color: #ff0000;">&quot;wget -O /tmp/world.sql.gz http://downloads.mysql.com/docs/world.sql.gz &amp;&amp; <span style="color: #000099; font-weight: bold;">\<br />
</span>gunzip /tmp/world.sql.gz &amp;&amp; mysql -u root -p -e 'create database if not exists world;' &amp;&amp; <span style="color: #000099; font-weight: bold;">\<br />
</span>mysql -u root -p world &lt; /tmp/world.sql &amp;&amp; rm /tmp/world.sql&quot;</span></div></td></tr></tbody></table></div>
<p>This pulls down the world database dump, unzips it, creates a DB to hold it, imports it, then removes the temporary files. You&#8217;ll be prompted twice for the password of the root MySQL user. You could also alter it to include the password if you are so inclined. Add the above alias line to ~/.bashrc, reload it, and you can have a test DB up and waiting within seconds anytime you want.</p>
    ]]></content:encoded>
			<wfw:commentRss>http://dancingpenguinsoflight.com/2009/09/rapidly-set-up-a-mysql-database-for-testing/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Troubleshooting with MySQL binary logs</title>
		<link>http://dancingpenguinsoflight.com/2009/09/troubleshooting-with-mysql-binary-logs/</link>
		<comments>http://dancingpenguinsoflight.com/2009/09/troubleshooting-with-mysql-binary-logs/#comments</comments>
		<pubDate>Mon, 07 Sep 2009 15:32:26 +0000</pubDate>
		<dc:creator>Samuel Huckins</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[administration]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://dancingpenguinsoflight.com/?p=1065</guid>
		<description><![CDATA[MySQL replication has a wide range of uses, including debugging applications writing to the DB being replicated. Once set up, all statements &#8220;that update data or potentially could have updated it&#8221; are stored in one or more binary logs (MySQL &#8230; <a href="http://dancingpenguinsoflight.com/2009/09/troubleshooting-with-mysql-binary-logs/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a title="MySQL manual on replication" target="_blank" href="http://dev.mysql.com/doc/refman/5.1/en/replication.html">MySQL replication</a> has a wide range of uses, including debugging applications writing to the DB being replicated. Once set up, all statements &#8220;that update data or potentially could have updated it&#8221; are stored in one or more binary logs (<a title="MySQL manual on the binary log" target="_blank" href="http://dev.mysql.com/doc/refman/5.0/en/binary-log.html">MySQL manual on the binary log</a>). So if something happens to your data and your application level logs aren&#8217;t cutting it, you can use the binary logs of the underlying DB as a source of information.</p>
<p>Assuming you have binary logging turned on, you first need to know where the binary logs are. The query &#8220;show binary logs;&#8221; will give you the filenames and sizes, but not the path. If you only set &#8220;log-bin&#8221; in my.cnf then the binary logs are placed in your data directory by default (find this by running &#8220;show variables like &#8216;datadir&#8217;;&#8221;). Otherwise they will be wherever you specified with &#8220;log-bin = /some/path&#8221;. If you passed the value via a command line option, run &#8220;ps aux | grep mysql&#8221; to view the options passed. If all else fails, run &#8220;sudo updatedb &#038;&#038; locate mysqld-bin&#8221;. </p>
<p>Now how to view these logs? There is in fact a handy utility for just this purpose: mysqlbinlog. Just pass it the name of the log file and it returns the text version. So if you only had a single search you could use:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #c20cb9; font-weight: bold;">sudo</span> mysqlbinlog <span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>mysql<span style="color: #000000; font-weight: bold;">/</span>mysqld-bin.000001 <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> foobar</div></td></tr></tbody></table></div>
<p>If you had a number of searches you could redirect to a file for processing at your own pace:</p>
<div class="codecolorer-container bash blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #c20cb9; font-weight: bold;">sudo</span> mysqlbinlog <span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>mysql<span style="color: #000000; font-weight: bold;">/</span>mysqld-bin.000001 <span style="color: #000000; font-weight: bold;">&gt;</span> mysqld-bin.000001_plain.txt</div></td></tr></tbody></table></div>
<p>This gives you the ability to search across all of the statements affecting your DB, as well as across all of the data coming in.</p>
    ]]></content:encoded>
			<wfw:commentRss>http://dancingpenguinsoflight.com/2009/09/troubleshooting-with-mysql-binary-logs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>mysql_secure_installation: A useful first step in securing a MySQL server</title>
		<link>http://dancingpenguinsoflight.com/2009/04/mysql_secure_installation-a-useful-first-step-in-securing-a-mysql-server/</link>
		<comments>http://dancingpenguinsoflight.com/2009/04/mysql_secure_installation-a-useful-first-step-in-securing-a-mysql-server/#comments</comments>
		<pubDate>Sat, 18 Apr 2009 14:55:54 +0000</pubDate>
		<dc:creator>Samuel Huckins</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[administration]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://dancingpenguinsoflight.com/?p=777</guid>
		<description><![CDATA[This won&#8217;t be an exhaustive post on how to secure a MySQL server. I just want to mention a useful utility packaged with MySQL server: mysql_secure_installation. Simply run it from the command line once MySQL server is installed and running. &#8230; <a href="http://dancingpenguinsoflight.com/2009/04/mysql_secure_installation-a-useful-first-step-in-securing-a-mysql-server/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>This won&#8217;t be an exhaustive post on how to secure a MySQL server. I just want to mention a useful utility packaged with MySQL server: <a target="_blank" title="mysql_secure_installation manual page" href="http://dev.mysql.com/doc/refman/5.0/en/mysql-secure-installation.html">mysql_secure_installation</a>. Simply run it from the command line once MySQL server is installed and running. It will prompt you with a series of questions, resulting in a more secure setup! </p>
<p>It only covers the very basics, but then you don&#8217;t need to remember those at least, and save yourself some typing to boot. Here&#8217;s what it does:</p>
<ul>
<li>Set a root password. If you already have it, you&#8217;ll need to enter it for the remaining steps.</li>
<li>Remove anonymous users</li>
<li>Disable non-local root access</li>
<li>Remove the test database and access rules related to it</li>
<li>Reload privilege tables so the above changes are in effect</li>
</ul>
<p>A quick and easy way to follow good practices.</p>
    ]]></content:encoded>
			<wfw:commentRss>http://dancingpenguinsoflight.com/2009/04/mysql_secure_installation-a-useful-first-step-in-securing-a-mysql-server/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Running MySQL queries in Python</title>
		<link>http://dancingpenguinsoflight.com/2009/03/running-mysql-queries-in-python/</link>
		<comments>http://dancingpenguinsoflight.com/2009/03/running-mysql-queries-in-python/#comments</comments>
		<pubDate>Sat, 21 Mar 2009 04:59:17 +0000</pubDate>
		<dc:creator>Samuel Huckins</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[scripting]]></category>

		<guid isPermaLink="false">http://dancingpenguinsoflight.com/?p=678</guid>
		<description><![CDATA[Being able to access MySQL databases in Python opens up quite a wide range of possibilities. It&#8217;s essential for a number of tasks such as connecting disparate datasources, performing maintenance, running regular updates, and more. While there are a number &#8230; <a href="http://dancingpenguinsoflight.com/2009/03/running-mysql-queries-in-python/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Being able to access MySQL databases in Python opens up quite a wide range of possibilities. It&#8217;s essential for a number of tasks such as connecting disparate datasources, performing maintenance, running regular updates, and more. While there are a number of helpful <a title="Google search for MySQL and Python tutorials" href="http://www.google.com/search?q=MySQL+and+Python+tutorials" target="_blank">tutorials out there</a> on how to connect to a MySQL database, they really just covers the basics and often fall short of describing a complete and <em>good</em> implementation, one you would want to use in production. That said, if you haven&#8217;t used the MySQLdb module before, I&#8217;d recommend skimming some of the tutorials out there (<a target="_blank" title="MySQLdb tutorial" href="http://www.devshed.com/c/a/Python/MySQL-Connectivity-With-Python/">this one is decent</a>), to get some initial familiarity with the process.</p>
<p>What follows is the setup I have settled on after a good bit of trial and error. It involves a little more effort than the minimum needed, but it&#8217;s a lot safer and more informative. It makes use of the logging module, whose setup I will assume. For more information on it, check out my article on <a title="Post on Python logging" href="http://dancingpenguinsoflight.com/2009/03/simple-and-effective-python-logging/" target="_blank">simple logging in Python</a>. You&#8217;ll wonder how you lived without it.</p>
<p>After developing with it for a while, I&#8217;ve found it&#8217;s easy to forget that the MySQLdb module isn&#8217;t included in the standard library. You need to verify it&#8217;s installed in the scripts you use it in. The following should suffice (assuming you aren&#8217;t using a package that sets up your dependencies):</p>
<div class="codecolorer-container python blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span><br />
<span style="color: #808080; font-style: italic;"># For MySQL DB access:</span><br />
<span style="color: #ff7700;font-weight:bold;">try</span>:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">import</span> MySQLdb<br />
<span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">ImportError</span>:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;You need to install the MySQLdb module. Check&quot;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;http://sourceforge.net/projects/mysql-python for details.&quot;</span><br />
&nbsp; &nbsp; <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span></div></td></tr></tbody></table></div>
<p>This lets you know where to go to find the module and exits with error.</p>
<p>Now you have access to the <a title="MySQLdb user's guide" href="http://mysql-python.sourceforge.net/MySQLdb.html" target="_blank">MySQLdb module</a>. But what&#8217;s the best way to access its functions? I have found it easiest to create a function that accepts a dictionary of the needed connection information as well as the query to run. It returns the data found, handling and logging errors. After this is in place, you only need to define your DB parameter dictionary (or load it from a config file), and then wrap the call to the query running function with a minimum of error handling. Here&#8217;s the function to perform the queries:</p>
<div class="codecolorer-container python blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">def</span> run_mysql<span style="color: black;">&#40;</span>params<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #483d8b;">&quot;&quot;&quot;Run MySQL query passed using passed connection information.<br />
&nbsp; &nbsp; &quot;&quot;&quot;</span><br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># If you want to see params for each connection attempt,</span><br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># uncomment the following line:</span><br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;">#logger.debug(&quot;Trying to connect with: %s&quot; % params)</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">try</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; db <span style="color: #66cc66;">=</span> MySQLdb.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">user</span><span style="color: #66cc66;">=</span>params<span style="color: black;">&#91;</span><span style="color: #483d8b;">'user'</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span> passwd<span style="color: #66cc66;">=</span>params<span style="color: black;">&#91;</span><span style="color: #483d8b;">'password'</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span> \<br />
&nbsp; &nbsp; &nbsp; &nbsp; db<span style="color: #66cc66;">=</span>params<span style="color: black;">&#91;</span><span style="color: #483d8b;">'database'</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span> unix_socket<span style="color: #66cc66;">=</span>params<span style="color: black;">&#91;</span><span style="color: #483d8b;">'socket'</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span> \<br />
&nbsp; &nbsp; &nbsp; &nbsp; host<span style="color: #66cc66;">=</span>params<span style="color: black;">&#91;</span><span style="color: #483d8b;">'host'</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span> port<span style="color: #66cc66;">=</span>params<span style="color: black;">&#91;</span><span style="color: #483d8b;">'port'</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span> use_unicode<span style="color: #66cc66;">=</span><span style="color: #008000;">True</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">except</span> MySQLdb.<span style="color: black;">Error</span><span style="color: #66cc66;">,</span> e:<br />
&nbsp; &nbsp; &nbsp; &nbsp; logger.<span style="color: black;">critical</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Error in connecting %d: %s&quot;</span> % <span style="color: black;">&#40;</span>e.<span style="color: black;">args</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span> e.<span style="color: black;">args</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; cursor <span style="color: #66cc66;">=</span> db.<span style="color: black;">cursor</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">try</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; cursor.<span style="color: black;">execute</span><span style="color: black;">&#40;</span>params<span style="color: black;">&#91;</span><span style="color: #483d8b;">'query'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; data <span style="color: #66cc66;">=</span> cursor.<span style="color: black;">fetchall</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># If you want to see how many rows were returned:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># rows_returned = cursor.rowcount</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">except</span> MySQLdb.<span style="color: black;">Error</span><span style="color: #66cc66;">,</span> e:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">raise</span> e<br />
&nbsp; &nbsp; &nbsp; &nbsp; cursor.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; db.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; cursor.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; db.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> data</div></td></tr></tbody></table></div>
<p>This would be called by:</p>
<div class="codecolorer-container python blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">db_params <span style="color: #66cc66;">=</span> <span style="color: black;">&#123;</span><span style="color: #483d8b;">'user'</span>:<span style="color: #483d8b;">'root'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'password'</span>:<span style="color: #483d8b;">'$3kr3t'</span><span style="color: #66cc66;">,</span><br />
<span style="color: #483d8b;">'database'</span>:<span style="color: #483d8b;">'test'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'socket'</span>:<span style="color: #483d8b;">'/var/run/mysqld/mysqld.sock'</span><span style="color: #66cc66;">,</span><br />
<span style="color: #483d8b;">'host'</span>:<span style="color: #483d8b;">'localhost'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'port'</span>:<span style="color: #ff4500;">3306</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'query'</span>:<span style="color: #483d8b;">'show tables;'</span><span style="color: black;">&#125;</span><br />
data <span style="color: #66cc66;">=</span> run_mysql<span style="color: black;">&#40;</span>db_params<span style="color: black;">&#41;</span><br />
<span style="color: #ff7700;font-weight:bold;">if</span> data:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Results:&quot;</span><span style="color: #66cc66;">,</span> data<br />
<span style="color: #ff7700;font-weight:bold;">else</span>:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;No data returned.&quot;</span></div></td></tr></tbody></table></div>
<p>This makes it simple to run any query against any database setup using a single function. The parameters included in db_params should cover most any Linux MySQL setup. One exception is socket, as this may differ between distributions. If you aren&#8217;t sure, just run &#8220;ps aux | grep mysql&#8221; and the process shown (assuming it&#8217;s running) should include a &#8220;&#8211;socket&#8221; option specifying where the socket file is. For servers on Windows, remove socket in favor of named pipes or shared memory. Or just use the TCP/IP default via port.</p>
<p>If there is an error trying to connect to the server, it is logged and the script exits. The log will include the numeric MySQL error code as well as a more or less helpful error message. <a target="_blank" title="MySQL page on error handling" href="http://dev.mysql.com/doc/refman/5.1/en/error-handling.html">Check out this page</a> for more info on MySQL error codes and message. This approach seems to work out well, since an issue in connecting means that there is likely either a problem with the database server, or our connection information is wrong. In either case, we will probably want to stop and re-write something.</p>
<p>If the connection is successful, it next attempts to run the query passed. If there is a problem, it raises the error to the calling function, then cleans up the database call and connection. Finally, the data are returned.</p>
<p>This function allows for fast access while being fairly simple and easy to follow. It has served me well. Here is a more complete example of its use:</p>
<div class="codecolorer-container python blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">def</span> retrieve_table_names<span style="color: black;">&#40;</span>db_params<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #483d8b;">&quot;&quot;&quot;Prints out all table names, using the database parameters passed.<br />
&nbsp; &nbsp; &quot;&quot;&quot;</span><br />
&nbsp; &nbsp; logger.<span style="color: black;">info</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Looking for tables in %s...&quot;</span> % db_params<span style="color: black;">&#91;</span><span style="color: #483d8b;">'database'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; db_params<span style="color: black;">&#91;</span><span style="color: #483d8b;">'query'</span><span style="color: black;">&#93;</span> <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;&quot;&quot;show tables;&quot;&quot;&quot;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">try</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; data <span style="color: #66cc66;">=</span> run_mysql<span style="color: black;">&#40;</span>db_params<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">except</span> MySQLdb.<span style="color: black;">Error</span><span style="color: #66cc66;">,</span> e:<br />
&nbsp; &nbsp; &nbsp; &nbsp; logger.<span style="color: black;">error</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Error in finding tables in %s: %s&quot;</span> % \<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: black;">&#40;</span>db_params<span style="color: black;">&#91;</span><span style="color: #483d8b;">'database'</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span> e<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> data:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Tables found:&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> data: <span style="color: #ff7700;font-weight:bold;">print</span> x<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; logger.<span style="color: black;">error</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;No tables found.&quot;</span><span style="color: black;">&#41;</span></div></td></tr></tbody></table></div>
<p>A word of caution: One thing that might be surprising is that queries resulting in warnings will error out. MySQL warnings aren&#8217;t always that bad. They might just be notes, which are informative and not critical in nature. I suggest writing queries that don&#8217;t generate actual warnings, and turn off note displays by turning setting the <a title="MySQL page on session variables" href="http://dev.mysql.com/doc/refman/5.1/en/server-session-variables.html#sysvar_sql_notes" target="_blank">sql_notes session variable</a> off (they really just don&#8217;t seem to be often useful).</p>
    ]]></content:encoded>
			<wfw:commentRss>http://dancingpenguinsoflight.com/2009/03/running-mysql-queries-in-python/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Finding the smallest or largest value across multiple columns in MySQL</title>
		<link>http://dancingpenguinsoflight.com/2009/03/finding-the-smallest-or-largest-value-across-multiple-columns-in-mysql/</link>
		<comments>http://dancingpenguinsoflight.com/2009/03/finding-the-smallest-or-largest-value-across-multiple-columns-in-mysql/#comments</comments>
		<pubDate>Sat, 21 Mar 2009 03:50:42 +0000</pubDate>
		<dc:creator>Samuel Huckins</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[efficiency]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://dancingpenguinsoflight.com/?p=716</guid>
		<description><![CDATA[A long title for a simple problem: You have a table containing several columns of, say, dates. You want to find out the first or last date among the values of these columns per row. Not too bad. But, you &#8230; <a href="http://dancingpenguinsoflight.com/2009/03/finding-the-smallest-or-largest-value-across-multiple-columns-in-mysql/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>A long title for a simple problem: You have a table containing several columns of, say, dates. You want to find out the first or last date among the values of these columns per row. Not too bad. But, you can&#8217;t just use <a title="MySQL manual on greatest()" href="http://dev.mysql.com/doc/refman/5.1/en/comparison-operators.html#function_greatest" target="_blank">greatest()</a> or <a title="MySQL manual on least()" href="http://dev.mysql.com/doc/refman/5.1/en/comparison-operators.html#function_least" target="_blank">least()</a>. Well, you could <a title="Bug report" href="http://bugs.mysql.com/bug.php?id=15610" target="_blank">before MySQL 5.0.13</a>. After that, the presence of any NULL values in the columns compared would result in NULL being returned. This is the proper implementation of the SQL standard, but it also means everyone depending on the old way was out of luck.</p>
<p>And so too are we who still need to find the extreme value among columns that can contain NULL! The problem might have been solved by MySQL releasing two new functions at the same time as the greatest()/least() changes that would perform the same operation as their old behavior, ignoring NULL values. It&#8217;s a common enough use case. But complaining won&#8217;t write queries.</p>
<p>The first attempt I made used a combination of least() with <a title="MySQL manual on coalesce()" href="http://dev.mysql.com/doc/refman/5.1/en/comparison-operators.html#function_coalesce" target="_blank">coalesce()</a>. This function returns the first non-NULL value among those passed. The problem with this approach is that any of the column values per row can be NULL along with any of the others. So I would have needed to cover all possible permutations, namely the number of columns to compare across squared! This gets immediately tedious. Consider the case for just four columns:</p>
<div class="codecolorer-container sql blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">SELECT</span> id<span style="color: #66cc66;">,</span> date1<span style="color: #66cc66;">,</span> date2<span style="color: #66cc66;">,</span> date3<span style="color: #66cc66;">,</span> date4<span style="color: #66cc66;">,</span><br />
least<span style="color: #66cc66;">&#40;</span><br />
<span style="color: #993333; font-weight: bold;">COALESCE</span><span style="color: #66cc66;">&#40;</span>date1<span style="color: #66cc66;">,</span> date2<span style="color: #66cc66;">,</span> date3<span style="color: #66cc66;">,</span> date4<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><br />
<span style="color: #993333; font-weight: bold;">COALESCE</span><span style="color: #66cc66;">&#40;</span>date2<span style="color: #66cc66;">,</span> date1<span style="color: #66cc66;">,</span> date3<span style="color: #66cc66;">,</span> date4<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><br />
<span style="color: #993333; font-weight: bold;">COALESCE</span><span style="color: #66cc66;">&#40;</span>date3<span style="color: #66cc66;">,</span> date2<span style="color: #66cc66;">,</span> date4<span style="color: #66cc66;">,</span> date1<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><br />
<span style="color: #993333; font-weight: bold;">COALESCE</span><span style="color: #66cc66;">&#40;</span>date4<span style="color: #66cc66;">,</span> date1<span style="color: #66cc66;">,</span> date2<span style="color: #66cc66;">,</span> date3<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><br />
# <span style="color: #cc66cc;">12</span> more permutations<span style="color: #66cc66;">...</span><br />
<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> first_date<br />
<span style="color: #993333; font-weight: bold;">FROM</span> my_db<span style="color: #66cc66;">.</span>my_table<br />
<span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> id;</div></td></tr></tbody></table></div>
<p>Yuck. I nearly wrote a script that would take the columns to be compared and generate the needed query.</p>
<p>Luckily, fellow information wrangler <a target="_blank" title="Zenoss team page" href="http://www.zenoss.com/about/team/">Bill Karpovich</a> suggested a much more elegant (and blissfully shorter) version:</p>
<div class="codecolorer-container sql blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">SELECT</span> id<span style="color: #66cc66;">,</span> date1<span style="color: #66cc66;">,</span> date2<span style="color: #66cc66;">,</span> date3<span style="color: #66cc66;">,</span> date4<span style="color: #66cc66;">,</span><br />
least<span style="color: #66cc66;">&#40;</span><br />
ifnull<span style="color: #66cc66;">&#40;</span>date1<span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'9999-99-99'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><br />
ifnull<span style="color: #66cc66;">&#40;</span>date2<span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'9999-99-99'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><br />
ifnull<span style="color: #66cc66;">&#40;</span>date3<span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'9999-99-99'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><br />
ifnull<span style="color: #66cc66;">&#40;</span>date4<span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'9999-99-99'</span><span style="color: #66cc66;">&#41;</span><br />
<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> first_date<br />
<span style="color: #993333; font-weight: bold;">FROM</span> my_db<span style="color: #66cc66;">.</span>my_table<br />
<span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> id;</div></td></tr></tbody></table></div>
<p>This checks each column to be examined, and considers NULL values to be equal to &#8217;9999-99-99&#8242;, which I feel safe in assuming is greater than any valid date I will have. This method fulfills this common need nicely, and in syntax only requires a number of statements linearly increasing with the number of columns.</p>
    ]]></content:encoded>
			<wfw:commentRss>http://dancingpenguinsoflight.com/2009/03/finding-the-smallest-or-largest-value-across-multiple-columns-in-mysql/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

