I have a SQL Azure database with two main tables that I am trying to join via a view. I have it working, but the execution time is in excess of 2 minutes.
Here are the main tables and columns I'm dealing with:
TransactionsTable:
PostedDate | EmployeeFirstName | EmployeeLastName | DollarsCollected | UserName
---------------------------------------------------------------------------------------------
09/08/2017 09:05 am | 'John' | 'Smith' | 42.25 | 'john.smith'
09/08/2017 09:07 am | 'Jane' | 'Jones' | 58.50 | 'jane.jones'
09/08/2017 09:15 am | 'Tom' | 'Holland' | 62.75 | 'tom.holland'
09/08/2017 09:17 am | 'John' | 'Smith' | 48.50 | 'john.smith'
09/08/2017 09:19 am | 'Jane' | 'Jones' | 32.25 | 'jane.jones'
CustomerHistory
CustomerID | StartDate | Duration | UserName | TransactionType
-----------------------------------------------------------------------------
1 | 09/08/2017 09:02 am | 600 | 'john.smit'h | 'PropertyTax'
2 | 09/08/2017 09:03 am | 500 | 'tom.holland' | 'TagRenewal'
3 | 09/08/2017 09:04 am | 450 | 'jane.jones' | 'PropertyTax'
4 | 09/08/2017 09:12 am | 700 | 'john.smith' | 'TagRenewal'
5 | 09/08/2017 09:16 am | 300 | 'jane.jones' | 'TagRenewal'
So, the deal here is - one employee can only have one customer at one time. If we know what time a transaction was posted and we know what employee posted it, then we should be able to connect that information to the CustomerHistory table by using the StartDate
and StartDate + Duration
as sort of an "umbrella" of the total transaction. Consider StartDate + Duration
to be equal to EndDate
. So, here's the query I'm trying to run to accomplish this:
SELECT
*
FROM
CustomerHistory
JOIN TransactionsTable ON
CustomerHistory.UserName = TransactionsTable.UserName
AND
TransactionsTable.PostedDate >= CustomerHistory.StartDate
AND
TransactionsTable.PostedDate <= DATEADD( ss, CustomerHistory.StartDate, CustomerHistory.Duration )
For reference, I have indexes on the UserName
fields as well as the date fields. Suffice it to say I'm oversimplifying my tables here, as there are many more columns of data from each table I am hoping to join. I have run the execution plan in SQL Server, and it tells me that the Hash Match will take about 38% of my execution time, and the table scan on the transaction table will take 42%. I am decent with SQL but have never delved into a query quite as resource intensive as what I'm dealing with here, and its putting quite a load on my server trying to run it this way.
Can anyone help?
It's tricky to speed up because your query is non-SARGable. Adding a persisted computed column I believe should work quite well for your query. You will want to read up on it though because this can slow DML(inserts,updates, and deletes).
My creation scripts of your table for reference(SQL Fiddle http://sqlfiddle.com/#!6/f1a39/8 ):
Create Table dbo.TransactionsTable
(
PostedDate Datetime,
EmployeeFirstName Varchar(100),
EmployeeLastName Varchar(100),
DollarsCollected Money,
UserName Varchar(100)
);
Create Table dbo.CustomerHistory
(
CustomerID Int,
StartDate DateTime,
Duration Int,
UserName Varchar(100),
TransactionType Varchar(100)
);
Insert Into dbo.TransactionsTable
Values
('09/08/2017 09:05 am','John','Smith',42.25 , 'john.smith'),
('09/08/2017 09:07 am','Jane','Jones',58.50 , 'jane.jones'),
('09/08/2017 09:15 am','Tom','Holland',62.75 , 'tom.holland'),
('09/08/2017 09:17 am','John','Smith',48.50 , 'john.smith'),
('09/08/2017 09:19 am','Jane','Jones',32.25 , 'jane.jones');
GO
Insert Into dbo.CustomerHistory
Values (1,'09/08/2017 09:02 am',600,'john.smith' ,'PropertyTax'),
(2,'09/08/2017 09:03 am',500,'tom.holland','TagRenewal'),
(3,'09/08/2017 09:04 am',450,'jane.jones','PropertyTax'),
(4,'09/08/2017 09:12 am',700,'john.smith','TagRenewal'),
(5,'09/08/2017 09:16 am',300,'jane.jones','TagRenewal');
Go
Make sure you have this index.
CREATE NONCLUSTERED INDEX ix_test1
ON TransactionsTable(UserName,PostedDate)
Include (EmployeeFirstName,EmployeeLastName,DollarsCollected);
GO
For customer history, can you add a persisted column? Then index the column
Alter Table CustomerHistory
Add EndDate As (DateAdd(ss,Duration,StartDate)) Persisted;
GO
CREATE NONCLUSTERED INDEX ix_test2
ON CustomerHistory(UserName,StartDate,EndDate)
Include(CustomerID,TransactionType);
GO
Here's the query
SELECT *
FROM CustomerHistory AS A
INNER JOIN TransactionsTable AS B
ON A.UserName = B.UserName
AND B.PostedDate Between A.StartDate And A.EndDate;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.