Press "Enter" to skip to content

Category: T-SQL

Copy-Pasta’d Temp Tables and More Fun

Andy Levy shares some thoughts:

I’ve spent a lot of time over the past 8 or years trying to “right the ship.” Systems that have been built and evolved over 10-15 years and the cracks are starting to show. Yes, there’s always the hot spot code that desperately needs attention, the stored procedure that runs in 6 hours but could be 20 minutes with the right adjustments. But I’m looking at a macro level today, more “operational” than “surgical.” When I see __ in a chunk of code, it’s a signal to me that there are overarching problems in how the whole system I’m working on was built and it’s going to take me a good, long while to undo that to deliver constant performance as data grows or improve maintainability.

Andy’s main topic is pre-populated temp tables serving as lookup tables in queries. Though if Andy wants eldrich temp table horrors, I raise him global temp tables (##table) created from a separate session and a SQL Agent job that runs every minute to create it, with people ignoring the failures because “That’s how it’s supposed to work.”

I’ve never seen that in practice, but now I kind of want to do it.

Bonus comment: leading semi-colons for CTEs. I rarely do that, but when I do, it’s because a semi-colon on the same line as a batch separator doesn’t count. In other words,

GO;

WITH records as (...)

returns an error. There might be some workable variant, admittedly, but in those cases, I do put the semi-colon in front of the CTE. The rest of the time, when I know there isn’t a batch separator right before the common table expression, I of course don’t. Commas and semi-colons belong at the end, not the beginning.

Leave a Comment

Subqueries in the SELECT Clause

Louis Davidson tries out a few query forms:

The post states that a query such as:

SELECT soh.SalesOrderID,(SELECT  C.AccountNumberFROM    Sales.Customer AS CWHERE   C.CustomerID = SOH.CustomerID)AS CustomerAccountNumberFROM   Sales.SalesOrderHeader SOH;

will, by definition, execute that subquery on the Customer object one time per row in the SalesOrderHeader table.

But is this true?

Click through as Louis tests a few variants of this using SQL Server.

Leave a Comment

Bad Query Signals

Mala Mahadevan takes advantage of an extra week:

I just managed to get a post in for this landmark T-SQL Tuesday, hosted by Brent Ozar. Brent was kind enough to keep the submission window open for two weeks instead of the usual one, and I was able to sneak a post in last – minute.

His invitation is to write about the things that immediately stand out as “bad signs” when reviewing a SQL query.

Click through for Mala’s list. It’s a good list. While some items Mala calls out are defensible and quite reasonable, there are some of them (such as a LEFT OUTER JOIN whose columns show up in the WHERE clause for filtering) that are simply not.

Leave a Comment

Two Pain Points in SQL Server Code

Steve Jones digs up a pair:

There are two things that immediately stand out to me when I see a query and create concern.

  1. cross joins
  2. functions in the where/on clause

While there are other things I might see, these two stand out and usually I can guess there will be issues.

Steve specifically calls out ANSI-89 style joins, which are awful. Before continuing, I agree with Steve’s points, but I figure I’d do a “yes, and” for this one.

When it comes to cross joins, there are specific circumstances in which I’ve written cross joins to great effect. The one that comes to mind most readily is when I need to create the raw data that will let you generate a matrix in a reporting tool.

Let’s say you want to know, for each sales territory and month, the number of new customers that month, the prior month, and the next month. The LAG() and LEAD() functions only work on rows, not intervals. Therefore, LAG() on the July row will show you the row prior to July. That might be June or it might be March, depending on how much data you have.

The solution, then, is to get the full set of months you care about from, say, a calendar table. Then, get the full set of sales territories. Cross join those two and you’ll have the entire range of relevant data. You can then left outer join to the actual data and fill in the gaps.

I have an example of this as a demo script on my Analyzing Business Data with T-SQL talk.

Leave a Comment

Red Flags in Query Design

Thomas Williams has a list:

Nowadays I look after 3rd-party databases more than internally-developed ones, so I accept there’s a whole lot of ex-best practices, vendor preferences, and possibly shortcuts in queries I might come across – whether it’s a poorly-performing query, a blocker, or an error.

(Although, when I developed software more frequently, I was guilty of all the gripes below. My start in SQL, last century, was poring over a big yellow “For Dummies” book. I was the dummy.)

Click through for the list. I particularly hate tibbling, a rather derisive term for the malformed version of Hungarian notation. This would just lead me down a rant about how systems Hungarian notation was a mess, whereas apps Hungarian notation can be useful in certain circumstances. Tibbling provides no semantically valuable information, which is why I dislike it so much.

Leave a Comment

T-SQL Code Smells

Rob Farley has a few:

I feel like I should preface this with a disclaimer. I added “potentially-” to the title, because there are many queries that might seem bad but can actually perform just fine. There are queries that on the surface can be great, but are nasty without a particular index, and there are queries that make me cringe a little when looking at them, but are actually okay. Brent Ozar is asking about signs of bad code for this month’s T-SQL Tuesday (the 200th – and I have a response for all 200 if you look back through my history of posts), and he wants us to write this for 2004 Brent, rather than 2026 Brent.

Click through for what Rob has come up with. I agree with all of Rob’s examples and do appreciate his usage of the APPLY operator as a way of solving one common problem.

Leave a Comment

Solving the Maximum Flow Problem in T-SQL

Sebastiao Pereira implements the Ford-Fulkerson algorithm:

Graphs can be used to formulate mathematical models for many different applications and one particular type of problem to be solved deals with networks that transport some kind of resource from one endpoint to another, like water or electricity. Is it possible to create using only SQL Server features?

What’s neat about this is that this sort of flow algorithm also works for, say, complex ETL processes. Also, in case you were as curious as I was, that map is Dresden.

Leave a Comment

When All Joins are Left

Hugo Kornelis gives an example of a red flag:

This anniversary edition is hosted by Brent Ozar. And his chose topic is: query red flags. Things that make you groan when you open a query and see them in the code. I’m sure there will be a ton of posts, because there are so many. I myself could probably fill a book with things I consider a red flag (and someone else would then point out that my queries have things that they consider red flags, but that is another discussion).

But let’s focus on just one thing in this post.

Hugo selects the case when all query joins are LEFT OUTER joins. Especially when the logic of the query mandates INNER joins.

Meanwhile, if all of your query joins are RIGHT OUTER joins, you’re just chaotic evil.

Leave a Comment

Red Flags in Database Code

Tom Zika has a list and starts with AI-generated code:

This one didn’t exist three years ago. Now it’s the first thing I look for.

To be clear, I’m not anti-AI. If the AI wrote clean code, I probably wouldn’t even notice. The red flag isn’t that AI generated it – it’s the patterns that give it away. I recently saw a real case where someone needed to update a set of values. Simple enough, right? Here’s what the AI-generated solution did:

Click through for a laugh, as well as several other red flags.

Leave a Comment