Press "Enter" to skip to content

Category: T-SQL

How OR Predicates Affect Indexes

Dualcore DBA adds a clause:

We’ve created an index on both of the columns in the WHERE clause both of which are also in the SELECT list. As a reminder, non-clustered indexes implicitly include the clustered index key in the included columns even if we have not explicitly specified it and so with this in mind, our index fully covers our query. This index should be good for an index seek right? Let’s execute our query again:

This solution isn’t the only way to SQL Server to use a specific pair of indexes—you can also use the UNION operator to replace one OR, for example. And that usually resolves the issue without needing index hints.

Leave a Comment

Challenges with DATE_BUCKET()

Erik Darling has a new video:

But what’s also strange here, too, is that SQL Server estimates one row very reliably for a date bucket. So, you know, you might be careful about that as well, especially if you’re returning far more than one row. You might be unhappy with the one row estimate.

It might bring you back to the bad old days of table variables and off histogram values, stuff like that. But, yeah, anyway, I had a point with all that. Let’s do this.

Click through to learn Erik’s point.

Leave a Comment

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.

Comments closed

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.

Comments closed

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.

Comments closed

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.

Comments closed

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.

Comments closed