T-SQL Statement Tracks Transaction-Less Dates

Downloads
102744.zip

My company provides pricing software and services for retailers and distributors in the consumer goods industry. One of the company engineers recently asked me to write a T-SQL statement that he could use to find out which stores didn't have any transactions during a one-week period. However, the data in the SQL Server table included only the IDs of the stores and the dates on which each store had a transaction. So, I was faced with the mind-challenging task of writing a T-SQL statement that would produce data that wasn't in the underlying table.

To demonstrate how the T-SQL statement I came up with works, I created the sample data shown in Table 1.


Table 1: Data in the MySalesTable Table



As you can see, it includes a week's worth of transaction dates (October 1-7, 2009) for five stores, which have the IDs of 100, 200, 300, 400, and 500. Only Store 500 has transaction dates for all seven days.

Listing 1 shows the T-SQL statement, GetNonTransactionDaysForStores.sql, I devised.


Listing 1: GetNonTransactionDaysForStores.sql (click to enlarge)



This code begins by using the FROM clause in callout A to produce two derived tables. This subquery first retrieves the unique Store_ID values from MySalesTable and puts them in a derived table named st1. If every store had a transaction on at least one day, the subquery returns every store ID once. The subquery then retrieves the unique TransactionDate values from MySalesTable and puts them in a derived table named st2. If a store has transactions on all seven days, the subquery returns all seven transaction dates.

The code in callout B performs a Cartesian product operation to match all rows in st1 with all rows in st2 in order to get every possible store-transaction date combination. The results in the Cartesian product (st3) are then filtered. Because we're interested in only those dates on which there weren't any transactions, the code looks for dates that are in st3 but not st2 for each store. Note that if none of the stores have a transaction on a certain day, the query won't return any result for that particular day for all the stores. The query assumes that at least one store will have a transaction on any given day in the specified date range.

Table 2 shows the results from running GetNonTransactionDaysForStores.sql.


Table 2: Results from GetNonTransactionDaysForStores.sql



As you can see, it displays only those stores that didn't have transactions (which is why store 500 isn't included) and the dates of those transaction-less days.

You can download GetNonTransactionDaysForStores.sql and the script I used to create and populate the sample table (MySalesTable.Table.sql) by clicking the 102744.zip hotlink. Note that because this code uses Cartesian product operation between the st1 and st2 tables, this solution doesn't scale well when you have more than a few thousand records to consider.

Discuss this Article 3

Ericjiang.yang
on Nov 9, 2009
If we use the new function "EXCEPT" provided by SQL Server 2005, the script will be much simple and efficient. I post the new script. select distinct I1.Store_ID , I2.TransactionDate from MySalesTable i1 left outer join MySalesTable i2 on I1.TransactionDate <> I2.TransactionDate except (Select Store_ID,TransactionDate from MySalesTable) Eric Jiang ericjiang.yang@gmail.com
RICK (not verified)
on Nov 5, 2009
So Saravanan, did you get fired after a "senior-senior production DBA" reviewed your code?!? I hate to see what a NON-senior production DBA would have done!
Barry (not verified)
on Dec 9, 2009
I think the real shortcoming here is that the solution given should have been written better. Either as this: Select distinct m1.Store_ID, m2.TransactionDate from MySalesTable m1 cross join MySalesTable m2 where m2.TransactionDate not in (Select m3.TransactionDate from MySalesTable m3 where m3.Store_ID=m1.Store_ID) or even more optimally as this: Select distinct m1.Store_ID, m2.TransactionDate from MySalesTable m1 cross join MySalesTable m2 where not exists (Select 1 from MySalesTable m3 where m3.Store_ID=m1.Store_ID and m3.TransactionDate=m2.TransactionDate)

Please or Register to post comments.

IT/Dev Connections

Las Vegas
September 30th - October 4th

Paul ThurottOur Experts will show you:
• Common SQL Server
Problems
• Best Practices for T-SQL
• SQL Server Integration
Services
• Database Development

Come See Michael Otey & Tim Ford in Person!

Early Registration Now Open

From the Blogs
May 21, 2013
blog

A Common Misconception about MAXDOP

Out of the box, SQL Server is (and has been) able to take advantage of multiple processors/cores without any effort on behalf of administrators....More
May 9, 2013
blog

My ISO 8601-Compliant Signature 2

My family recently just "officially" announced that we're in the process of adopting a child from South Africa. We're quite excited, of course, but there's a ton of paperwork to do—along with the need for gobs of signatures....More
May 8, 2013
blog

Use SSIS for ETL from Hadoop

In this blog post, Mark Kromer walks you through using SSIS as a way to use ETL techniques using Microsoft's Hadoop on Windows (HDInsight) as a source using Hive connectors...More
SQL Server Pro Forums

Get answers to questions, share tips, and engage with the SQL Server community in our Forums.