views:

316

answers:

3

Right now I have this SQL query which is valid but always times out:

SELECT 
(
SELECT (MAX(WP_ODOMETER) - MIN(WP_ODOMETER)) / DATEDIFF(DAY, MIN(WP_DATETIME), MAX(WP_DATETIME))
FROM WAYPOINTS
WHERE WP_DATETIME BETWEEN DATEADD(DAY,-14,GETDATE()) AND GETDATE()
AND WP_VTDID = 'L088'
)
AS MAXD, 
(
SELECT MAX(WP_ODOMETER) 
FROM WAYPOINTS
WHERE WP_DATETIME BETWEEN DATEADD(DAY,-14,GETDATE()) AND GETDATE()
AND WP_VTDID = 'L088'
)
AS MD

I want to create a view based on the above SQL query. Something like this:

SELECT L_VTDID
(
SELECT (MAX(WP_ODOMETER) - MIN(WP_ODOMETER)) / DATEDIFF(DAY, MIN(WP_DATETIME), MAX(WP_DATETIME))
FROM WAYPOINTS
WHERE WP_DATETIME BETWEEN DATEADD(DAY,-14,GETDATE()) AND GETDATE()
AND WP_VTDID = LOCOMOTIVES.L_VTDID
)
AS MAXD, 
(
SELECT MAX(WP_ODOMETER) 
FROM WAYPOINTS
WHERE WP_DATETIME BETWEEN DATEADD(DAY,-14,GETDATE()) AND GETDATE()
AND WP_VTDID = LOCOMOTIVES.L_VTDID
)
AS MD
FROM LOCOMOTIVES
A: 

Is WAYPOINTS indexed on WP_DATETIME and WP_VTDID?

lc
yes, all important fields on that table already indexed
Dels
Better to state which fields are indexed - you might not know which ones are important. Also, are there any compound indexes (on several columns) or are they all single column indexes. What is the size of the table (number of rows, width of row in bytes, number of columns).
Jonathan Leffler
+1  A: 

Since they have the same where clause, you could combine them:

SELECT 
MAX(WP_ODOMETER),
(MAX(WP_ODOMETER) - MIN(WP_ODOMETER)) / 
DATEDIFF(DAY, MIN(WP_DATETIME), MAX(WP_DATETIME))
FROM WAYPOINTS
WHERE WP_DATETIME BETWEEN DATEADD(DAY,-14,GETDATE()) AND GETDATE()
AND WP_VTDID = 'L088'

An index on WP_VTDID, WP_DATETIME can speed this up. You could also include WP_ODOMETER in the index, to save the bookmark lookup from the index to the table itself.

If the timeout occurs because someone else is locking the table, try to change the from statement to:

FROM WAYPOINTS (NOLOCK)

If the query runs fine with NOLOCK, another process is using the table and preventing your query from locking rows.

Andomar
i use your query too at first, but it seem slower, so i use inner select to speed up (maybe i wrong), and yes i already indexed the important fields
Dels
Did you check the query execution plan? Menu query, then actual or estimated execution plan. If you see a table scan there, tine index is probably not being used.
Andomar
why this obsession with NOLOCK ????
Sam Saffron
@Andomar: nope it didn't seek the tables, but seek the clustered index (about 34% for each field)
Dels
You could add the execution plan to the post, it will be output as text if you include "set showplan_text on" on top of your query (seperate from query with "go".) If possible add the defintion of the indexes.
Andomar
+3  A: 

Believe it or not, client side languages are actually quite capable of doing subtraction and division, etc. So, were it up to me, I would simplify the query (especially since this version gives trouble):

SELECT MAX(WP_ODOMETER) AS MAX_ODO,
       MIN(WP_ODOMETER) AS MIN_ODO, 
       MIN(WP_DATETIME) AS MIN_DATE,
       MAX(WP_DATETIME) AS MAX_DARE
  FROM WAYPOINTS
 WHERE WP_DATETIME BETWEEN DATEADD(DAY,-14,GETDATE()) AND GETDATE()
   AND WP_VTDID = 'L088'

If there is a major problem with handling date computations on the client side, then I'd concede that you might need to generate the difference between MAX_DATE and MIN_DATE on the server, but it might be better to get a host language that allows you to do date computations.

Jonathan Leffler
How would shifting a single division from the server to the client speed up a slow query?
Andomar
It isn't moving the division; it is replacing two sub-queries in the SELECT list with a simpler set of expressions that helps. The original query calculates both 'MAX_ODO' and the expression over time (roughly, average distance travelled per day) as two separate sub-queries. I've replaced them by a single (non-sub-)query.
Jonathan Leffler