<?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>Webninja.org &#187; Neat Stuff</title>
	<atom:link href="http://webninja.org/archives/category/neat-stuff/feed" rel="self" type="application/rss+xml" />
	<link>http://webninja.org</link>
	<description>The digital biography of Justin King</description>
	<lastBuildDate>Wed, 13 May 2009 02:13:54 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Fun with SQL and in line queries</title>
		<link>http://webninja.org/archives/46</link>
		<comments>http://webninja.org/archives/46#comments</comments>
		<pubDate>Sun, 29 Jul 2007 17:40:36 +0000</pubDate>
		<dc:creator>Justin</dc:creator>
				<category><![CDATA[Neat Stuff]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://webninja.org/archives/46</guid>
		<description><![CDATA[So I&#8217;ve grown to not like the coding style of the guy before me at all. Some of his methods are quite, recursive and hellish when it comes to SQL. Several times, the easy way was taken rather than the correct way. To give you a bit of background, the main application I support controls [...]]]></description>
			<content:encoded><![CDATA[<p>So I&#8217;ve grown to not like the coding style of the guy before me at all.  Some of his methods are quite, recursive and hellish when it comes to SQL.  Several times, the easy way was taken rather than the correct way.  To give you a bit of background, the main application I support controls at outbound call center.  Agents log into the system and dial out with it.  In order to track what a current agent is doing there is a table called actions.  Everything from logging in, logging out, and more is logged here.  Over the past 2 years, this has led to over 7 million records in the table.   If you&#8217;re not a tech person, it&#8217;s about to get deep.</p>
<p>In order to determine if a user is logged in, the previous programmer would do the following.  Query the database for all users with a type of 2 (call center agent).   After that  for each user in the database of type 2 (call center agents, currently ~120 agents exist), he would query the actions table for the users last action, whether it&#8217;s action type 1 (login) or 2 (logout).  If the first returned row is of action type 1, the user is logged in.  Lastly, the code queries the actions table to see what the last campaign a user logged into.  (action type 20).  After throwing in some basic code to track the queries and time of this (and thanking John Davis along the way for teaching the importance of big O notation) I learned that an average check of who&#8217;s logged in totaled around 150-200 queries along with taking 45 seconds to a minute.  So this was one of my goals in Nashville last week, to write one massive query I could use to get the results I&#8217;m looking for.   To assist me in the insanity, I called master of all that is shoes, <a href="http://http://shoefalsefiction.blogspot.com/"><strong>Brian Schumacher</strong></a>.  We worked together back at Irresistible Ink as data developers and since he&#8217;s gone on to be a DBA in Klamath Falls, Oregon.  Well he quit last week but that&#8217;s his story not mine.</p>
<p>So after about 45 minutes of being on the phone and utilizing the greatness that is <a href="http://www.pastebin.com">pastebin</a>, we worked out a viable solution.  I present to you, possibly the most complicated query I&#8217;ve written to date.</p>
<p><code class="prettyprint">SELECT<br />
	loggedIn.lastname, loggedIn.firstname, campaigns.cpnname, DATEDIFF(ss,[actions_4].[actionwhen],getdate()) AS LoggedIn, DATEDIFF(ss,[actions_3].[actionwhen],getdate()) AS CampaignLogin<br />
FROM<br />
	(<br />
		SELECT<br />
			employees.unqempid, employees.lastname, employees.firstname, ActionIDLoggedIn.actionID<br />
		FROM<br />
		(<br />
			SELECT<br />
				unqempid, MAX(actionid) AS actionID<br />
			FROM<br />
				actions<br />
			WHERE<br />
				(actiontypeid = '1')<br />
			GROUP BY unqempid<br />
    ) AS ActionIDLoggedIn<br />
		INNER JOIN<br />
		(<br />
			SELECT<br />
				unqempid, MAX(actionid) AS actionID<br />
			FROM<br />
				actions AS actions_2<br />
			WHERE<br />
				(actiontypeid = '2')<br />
			GROUP BY<br />
				unqempid<br />
     ) AS ActionIDLoggedOut<br />
		ON<br />
			ActionIDLoggedIn.unqempid = ActionIDLoggedOut.unqempid AND<br />
			ActionIDLoggedIn.actionID > ActionIDLoggedOut.actionID<br />
			INNER JOIN<br />
				employees ON employees.unqempid = ActionIDLoggedIn.unqempid<br />
			WHERE      (employees.type = 2)<br />
  ) AS loggedIn<br />
INNER JOIN<br />
(<br />
	SELECT<br />
		unqempid, MAX(actionid) AS actionID<br />
	FROM<br />
		actions AS actions_1<br />
	WHERE<br />
		(actiontypeid = '20')<br />
	GROUP BY<br />
		unqempid<br />
) AS maxCampaign<br />
ON maxCampaign.unqempid = loggedIn.unqempid<br />
INNER JOIN<br />
	actions AS actions_3 ON maxCampaign.actionID = actions_3.actionid<br />
INNER JOIN<br />
	campaigns ON actions_3.actioninfo = campaigns.cpnid<br />
INNER JOIN<br />
	actions AS actions_4 ON loggedIn.actionID = actions_4.actionid<br />
ORDER BY<br />
  loggedIn.lastname, loggedIn.firstname<br />
</code></p>
<p>The end result, we&#8217;ve shortened this down to 1 query that takes 2-3 seconds.  Hopefully this post can only serve as help to some programmer stumbling along a similar problem as mine.</p>
]]></content:encoded>
			<wfw:commentRss>http://webninja.org/archives/46/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pownce</title>
		<link>http://webninja.org/archives/39</link>
		<comments>http://webninja.org/archives/39#comments</comments>
		<pubDate>Thu, 12 Jul 2007 13:56:40 +0000</pubDate>
		<dc:creator>Justin</dc:creator>
				<category><![CDATA[Neat Stuff]]></category>

		<guid isPermaLink="false">http://webninja.org/archives/39</guid>
		<description><![CDATA[So my long time e-friend ht recently sent me an invite to Pownce. Pownce is alot like Twitter but from one of the guys over at Digg. The basis of the site is a social network that appears to be taking a minimal approach. Where Myspace and Facebook bombard you with bulletins, event invites, friend [...]]]></description>
			<content:encoded><![CDATA[<p>So my long time e-friend ht recently sent me an invite to <a href="http://www.pownce.com">Pownce</a>. Pownce is alot like Twitter but from one of the guys over at Digg.  The basis of the site is a social network that appears to be taking a minimal approach.  Where Myspace and Facebook bombard you with bulletins, event invites, friend requests, and individual pages, Pownce takes a more minimal approach, giving you the data you need and that&#8217;s it.  At present I don&#8217;t see any ads however the mention of going pro offers sending files up to 100MB and no ads for a reasonable $20 / year.  Whether I&#8217;ll hold on to this or watch it fade away as another page I&#8217;ve made an account for I&#8217;m not sure yet.  If I keep using it I&#8217;ll write up a list of pros and cons.  Until then, if you&#8217;d like an invite to the invite-beta, let me know and I&#8217;ll send one over.</p>
]]></content:encoded>
			<wfw:commentRss>http://webninja.org/archives/39/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
