Matt Velic

Data and Design

SELECT * FROM ZipLock

January 23, 2012 by Matt | 0 comments

I saw this commercial a while ago, but found a copy of it on YouTube only recently. (Thankfully Congress dropped SOPA/PIPA, so I feel safe sharing it…) Anyway, this is a bit how it’s like when writing a query with SELECT *. We don’t have the convenience of a plastic bag to save the unused data from an errant query, so show responsibility and add the columns you really need.

January 17, 2012
by Matt
1 Comment

Let’s Get Recursive!

Recently I was asked about how I might show relationships between different entities within the same table. That one object might be the parent of another, and the child might have children or grandchildren of its own. To date, the person making the inquiry had been using a secondary table in order to work out these relationships, but he thought that there was probably a better way.

I replied, “You are absolutely right that there is a better way: you can use Recursive CTEs!”

The CTE, Recursed

To quote SQL Server Books Online, “A common table expression (CTE) can be thought of as a temporary result set that is defined within the execution scope of a single SELECT, INSERT, UPDATE, DELETE, or CREATE VIEW statement.” So what makes a CTE recursive? It references itself over and over, building subsets until it has returned the whole results set. A bit of a warning: you can only use CTEs with SQL Server 2005 or later.

To start, let’s use TempDB and create some data so we can play. We’re creating a single table, dbo.Family, and it is self-referencing in that both Parents and Children are stored inside of it. You can tell the top-most Parent when a row doesn’t have an ID listed in the ParentID field. If it does, it means that the row is the child of another, and the ID listed is the Parent’s MainID. (I know, it’s not at all confusing.) Once you create the table and populate the data, you can run the SELECT statement and see the normal output.

USE tempdb;
GO

CREATE TABLE dbo.Family (
	MainID INT NOT NULL IDENTITY PRIMARY KEY
	,ParentID INT NULL
	,Name VARCHAR(35) NOT NULL
);

ALTER TABLE dbo.Family
ADD CONSTRAINT FK_ParentChild FOREIGN KEY (ParentID)
	REFERENCES dbo.Family (MainID);
GO

INSERT INTO dbo.Family (ParentID, Name)
VALUES (NULL,'Parent A')
,(1,'Child A')
,(2,'Grandchild A1')
,(2,'Grandchild A2')
,(NULL,'Parent B')
,(NULL,'Parent C')
,(5,'Child B1')
,(6,'Child C')
,(5,'Child B2')
,(8,'Grandchild C')
,(10,'Great-Grandchild C');
GO

SELECT MainID, ParentID, Name
FROM dbo.Family;
A basic SELECT statement result set.

SELECT * FROM dbo.Family

The Boring Syntax Part

As you’ll see in the examples below, the CTE part of the query is the SELECT statement wrapped in parathesis and setting on top of the normal SELECT statement. This simple query must begin with the keyword WITH, and then you’d name your CTE. I’ve named mine reCTE. Another warning: because of the keyword WITH, all previous statements must be closed with a semi-colon (;). You may often see others write their CTEs as “;WITH reCTE” with the semi-colon preceding the keyword. It’s a safety measure as the whole query will fail if the previous statement hasn’t been closed yet. Additionally, I like to include explicit column names, though you don’t have to.

As for the CTE, it is your basic SELECT statement. It’s used to build the temporary set that the final SELECT statement can use; it’s similar to using a temp table. To make a CTE recursive, you simply add a UNION ALL. When using UNION ALL, the number of columns must be equal between the two sets, and they must be in the same order and share the same data type in order for the UNION to function properly.

As you’ll see in the example queries below, the first SELECT query is called the Anchor Member. It returns a valid table that’s used as the basis of the recursion. The query that follows the UNION ALL is termed the Recursive Member. It’s the query that is run against the anchor until the complete set has been returned.

Power of Recursion

As before, this functionality is available to users of SQL Server 2005 and later. What about the times before SQL 2005? Well, you had to rely on some seconday table in order to recurse through a results set. Using CTEs, you can encapsulate this within a single query. One common request is to see how “deep” a family is. This might come in the guise of managers to subordinates in displaying how flat (or deep) an organizational chart is.

WITH reCTE (MainID, ParentID, Name, Depth) AS (
	--Anchor Member
	SELECT f.MainID, f.ParentID, f.Name, 1 AS Depth
	FROM dbo.Family as f
	WHERE f.ParentID IS NULL
	UNION ALL
	--Recursive Member
	SELECT f.MainID, f.ParentID, f.Name, Depth + 1
	FROM dbo.Family as f
	INNER JOIN reCTE
		ON f.ParentID = reCTE.MainID
)
SELECT reCTE.MainID, reCTE.ParentID, reCTE.Name, reCTE.Depth
FROM reCTE
ORDER BY reCTE.Depth, reCTE.MainID;
Result set from a recursive CTE query showing the overall depth between the absolute Parent records and the lowest Child records.

How Low Can You Go?

As above, the Anchor Member is used to set the basic result. In this case, we’re querying for the absolute Parents in the set. The Recursive Member follows the UNION ALL, and we actually reference the CTE in a JOIN while still defining reCTE as a whole. This is what makes it recursive.

The outer query returns the set we’ve created with the CTE. For the above set, there are four levels of depth. This could translate to an organizational chart, or in discovering one’s secondary and tertiary managers.

Another common use for the recursive CTE is to find all relationships to a single Parent. With a little modification, we can use nearly the same query but aim for finding all the subordinates to Parent A by changing the WHERE clause in our Anchor to a specific MainID.

WITH reCTE (MainID, ParentID, Name) AS (
	--Anchor Member
	SELECT f.MainID, f.ParentID, f.Name
	FROM dbo.Family as f
	WHERE f.MainID = 1
	UNION ALL
	--Recursive Member
	SELECT f.MainID, f.ParentID, f.Name
	FROM dbo.Family as f
	INNER JOIN reCTE
		ON f.ParentID = reCTE.MainID
)
SELECT reCTE.MainID, reCTE.ParentID, reCTE.Name
FROM reCTE
ORDER BY reCTE.MainID;
Recursive CTE query that selects the lineage of Parents and Children based on a single ID.

Who is in this Family?

That’s all I’ve got on CTEs for now. If you want to learn even more, check out Audrey Hammond’s talk on the subject. It’s number 18 on the list, and it’ll require a PASS login, but it’s well worth it. She’s quite the awesome T-SQL Wizard.

meme15new

January 16, 2012
by Matt
1 Comment

The Twitters

Jason has asked about our Twitter usage, specifically how it has helped us as DBAs or developers, or in our careers as general.

Microblog… Something Else… Profit!

Tweet tweet^ - geograph.org.uk - 1134223

A Big, Wooden Twitter!

I didn’t get Twitter at first. I thought that it was a service for self-involved folks to talk incessantly about what they ate at each meal. I sometimes fail in having the best confidence, and I thought, “Who would even care to learn about what I ate?”

But I didn’t get Twitter; I didn’t understand how people were using it. Sure, there are plenty of people who Tweet about what they ate for lunch, what they bought at the store, what location they just checked in to (and that you are free to rob their houses while they’re away) – and even I’m guilty of such behavior from time to time – but this isn’t want Twitter is about. Twitter isn’t about broadcasting; it’s about having conversations.

Twitter is a public, global chat room, except it’s cooler than AOL ever was and you can tune in to just the people you want to hear.

How I Use Twitter

When I was unceremoniously handed the role of Accidental DBA, I was alone. I had no one to go to with questions. I didn’t even have the support of the IT department. What I had was a SQL Server database, the knowledge of how to restart IIS via Command Line (seriously, don’t ask…), and a lot of questions around, “How would I even know if something were going wrong?”

Like any good geek, I turned to Google for answers. But it wasn’t until I ran across Brent Ozar’s blog and found his Simple Twitter book that I was sold enough to give Twitter a try.

Twitter saved me. Twitter became my support system at work. Twitter became a way to ask questions, double check assumptions, verify functionality, and blow off steam. Twitter became a way to find new blogs to read, and to share new blogs that I’ve written. Simply watching the #SQLHelp hashtag through the day opened me to new and often-times esoteric knowledge that I probably wouldn’t have encountered on my own.

How Should You Use Twitter?

Well, you first have to sign up for an account! After that, download a Twitter client to help you manage it. In the past I would’ve easily recommended TweetDeck, but they’ve made some changes to their app recently that I don’t fully approve but at least you can run it in a browser. (Yeah, I know: it’s free so get over it.) Do some searches for #SQLServer, #SQLHelp, #SQLPeople and #SQLPass to find some interesting and knowledgeable people to follow. And then…

Jump into the conversation! Offer your opinion, help in answering a question. Don’t hesitate, don’t become a lurker. Like I mentioned, Twitter is about conversation, and sure, you’ll often times jump in right in the middle of things, but that’s how the SQL Community rolls on Twitter. And it’s funny how a conversation can thread from clustering to coffee to bacon in a matter of minutes.

Come and join in!

January 9, 2012
by Matt
0 comments

meme Monday January 2012

Tom LaRock asked what we want to do for our #SQLFamily in the new year: I want to continue bringing the awesomeness of SQLPeople to the community.

Beginning today, you can access the newly released video library from SQLInspire NYC 2011. Seven inspirational talks, fourteen videos filled with wonderful stories and knowledge. Go and consume. Change your life and the SQL community.