patternsqlMinor
SQL query returns different results when index is dropped
Viewed 0 times
indexsqldroppedquerydifferentreturnswhenresults
Problem
In SQL Server 2000 SP4, I have a query
PS_BUS_UNIT_TBL_AP has a unique clustered index on it. If the index is present, the above query results in a division by zero in
despite the fact that the query explicitly excludes rows where VAT_CALC_AMT is zero.
If the in
SELECT
FROM PS_VED_VCH_TAO5 A
,PS_BUS_UNIT_TBL_AP B
,PS_RT_DFLT_VW C
WHERE A.PROCESS_INSTANCE = 594170
AND A.VAT_CALC_AMT <> 0
AND A.VAT_ENTRD_AMT <> 0
AND A.VAT_ENTRD_AMT <> A.VAT_CALC_AMT
AND A.BUSINESS_UNIT = B.BUSINESS_UNIT
AND A.VCHR_SRC <> 'PROC'
AND B.VCHR_VAT_MSG_OPT = 'E'
AND A.VAT_CALC_TYPE = 'E'
AND A.VAT_RCRD_INPT_FLG = 'Y'
AND A.VAT_RCRD_OUTPT_FLG = 'N'
AND C.FROM_CUR = A.TXN_CURRENCY_CD
AND (
(C.TO_CUR = A.VAT_TOL_CUR_CD AND C.RT_TYPE = A.VAT_TOL_RT_TYPE)
OR
(C.TO_CUR = A.TXN_CURRENCY_CD AND C.RT_TYPE = A.RT_TYPE AND A.VAT_TOL_CUR_CD = ' ' AND A.VAT_TOL_RT_TYPE = ' ')
)
AND C.EFFDT =
(
SELECT MAX(I.EFFDT)
FROM PS_RT_DFLT_VW I
WHERE I.FROM_CUR = C.FROM_CUR
AND I.TO_CUR = C.TO_CUR
AND I.RT_TYPE = C.RT_TYPE
AND I.EFFDT <= A.INVOICE_DT
)
AND
(
((A.VAT_TOL_AMT < (((((A.VAT_ENTRD_AMT - A.VAT_CALC_AMT)) / ( C.RATE_DIV))) * ( C.RATE_MULT)))
OR
(A.VAT_TOL_AMT < (((((((A.VAT_ENTRD_AMT - A.VAT_CALC_AMT)) / ( C.RATE_DIV))) * ( C.RATE_MULT))) * ( -1)))
)
AND
(
(A.VAT_TOL_PCT < (((((A.VAT_ENTRD_AMT - A.VAT_CALC_AMT)) / ( A.VAT_CALC_AMT))) * ( 100)))
OR
(A.VAT_TOL_PCT < (((((((A.VAT_ENTRD_AMT - A.VAT_CALC_AMT)) / ( A.VAT_CALC_AMT))) * ( 100))) * ( 1)))
)
)PS_BUS_UNIT_TBL_AP has a unique clustered index on it. If the index is present, the above query results in a division by zero in
(A.VAT_TOL_PCT < (((((((A.VAT_ENTRD_AMT - A.VAT_CALC_AMT)) / ( A.VAT_CALC_AMT))) * ( 100))) * ( 1)))despite the fact that the query explicitly excludes rows where VAT_CALC_AMT is zero.
If the in
Solution
When you create/drop the index, you also affect SQL Server Query Optimizer's plan created to service your query.
Have a look at this Connect item.
Basically, SQL Server is free to optimise the expressions in the SELECT clause prior to applying the WHERE conditions. Not very intuitive, but someone decided it should do so.
Normally, to avoid divide by zero errors, I throw a NULLIF in there which is sufficient to get past the error while not really affecting the result (since the WHERE clause actually prunes them).
e.g.
Have a look at this Connect item.
Basically, SQL Server is free to optimise the expressions in the SELECT clause prior to applying the WHERE conditions. Not very intuitive, but someone decided it should do so.
Normally, to avoid divide by zero errors, I throw a NULLIF in there which is sufficient to get past the error while not really affecting the result (since the WHERE clause actually prunes them).
e.g.
(A.VAT_TOL_PCT < (((((((A.VAT_ENTRD_AMT - A.VAT_CALC_AMT)) / ( NULLIF(A.VAT_CALC_AMT,0)))) * ( 100))) * ( 1)))Code Snippets
(A.VAT_TOL_PCT < (((((((A.VAT_ENTRD_AMT - A.VAT_CALC_AMT)) / ( NULLIF(A.VAT_CALC_AMT,0)))) * ( 100))) * ( 1)))Context
StackExchange Database Administrators Q#27861, answer score: 3
Revisions (0)
No revisions yet.