March 13, 2009 at 1:49 pm
I have the below update statement inside a big procedure. If I comment the below portion, I am saving 10-15 minutes...Can somebody tell me how can I improve the below statment.
=====================================================================================
begin
update dbo.state_income
set totall_cityinc = ( case when (isnull(citypt,0) <>0 and isnull(distpt,0) <>0) then (citypt/distpt*100) else totall_cityinc end )
from
(
select
stateid ,
cityid,
districtid,
(districtpoint) as distpt,
(COALESCE(citypoint,1,0)) as citypt
from dbo.city
where
active = 1
group by stateid ,cityid, districtid
) t1 where stateid=@stateid and city=@cityid )
WHERE stateid=@stateid and city=@cityid
end
March 13, 2009 at 2:17 pm
The first course of action when attempting this sort of exercise is
to try and work out what the code is trying to achieve.
In this case your derived table (t1) will return multiple rows, but the where
clause is on stateid and city, which are probably the same in every row, and not
joined in any way to state_income, meaning that the total_cityinc column will be
updated with a random value from t1.
If you want any help with this we will need more info.
At the very least we will need a sample schema, and an explanation of exactly what
the code is supposed to do.
March 13, 2009 at 2:25 pm
You can help us help you by reading the first article I have linked in my signature block below that regarding asking for assistance.
March 14, 2009 at 1:16 pm
Heh... the first step towards troubleshooting any code is to make it readable... when I do that to your code example, a certain problem with the code sticks out like a sore thumb...
update dbo.state_income
set totall_cityinc = (
case
when (isnull(citypt,0) <>0
and isnull(distpt,0) <>0)
then (citypt/distpt*100)
else totall_cityinc
end
)
from (
select stateid ,
cityid,
districtid,
districtpoint as distpt,
COALESCE(citypoint,1,0) as citypt
from dbo.city
where active = 1
group by stateid ,cityid, districtid
) t1
where stateid=@stateid and city=@cityid ) --<<<Paren will certainly cause an error here
WHERE stateid=@stateid and city=@cityid
BUT, that's not what's causing the performance problem. What's causing your performance problem is two fold... first, you've used an illegal form of UPDATE in that you have a join in an UPDATE and the target table is not in the FROM clause. If you look in Books Online, you will never see such an example.
Second, the absence of a proper join to the target table makes for a cross join. Further, I believe you want to add DistrictID to the join. If not, then remove it from the inner join as it serves no purpose other than to make a partial cross join that that violates the intent of the update.
Here's the code... I'd really appreciate it if you'd spent a little time formatting your own code in the future to make it easier on those of us who try to help.
update dbo.state_income
set totall_cityinc = case
when isnull(citypt,0) <>0
and isnull(distpt,0) <>0
then (citypt/distpt*100)
else totall_cityinc
end
from dbo.State_Income si --added
INNER JOIN
(
select stateid ,
cityid,
districtid,
districtpoint as distpt,
COALESCE(citypoint,1,0) as citypt
from dbo.city
where active = 1
and stateid=@stateid and city=@cityid --added
group by stateid ,cityid, districtid
) t1
ON si.StatID = t1.StateID, --added
AND si.CityID = t1.CityID, --added
AND si.DistrictID = t1.DistrictID --added
--Jeff Moden
Change is inevitable... Change for the better is not.
March 14, 2009 at 8:14 pm
if you want you can try using Common Table Expression (CTE) method.. ans see how long it will take
WITH CITY_INFO(stateid ,cityid,districtid,distpt,citypt
(
select stateid ,
cityid,
districtid,
districtpoint as distpt,
COALESCE(citypoint,1,0) as citypt
from dbo.city
where active = 1
and stateid=@stateid and city=@cityid --added
group by stateid ,cityid, districtid
)
update dbo.state_income
set totall_cityinc = case
when isnull(citypt,0) <>0
and isnull(distpt,0) <>0
then (citypt/distpt*100)
else totall_cityinc
end
from dbo.State_Income si --added
INNER JOIN CITY_INFO t1
ON si.StatID = t1.StateID, --added
AND si.CityID = t1.CityID, --added
AND si.DistrictID = t1.DistrictID --added
Hi Jeff - will CTE be fine to use in this context..
March 14, 2009 at 9:35 pm
Joseph (3/14/2009)
if you want you can try using Common Table Expression (CTE) method.. ans see how long it will takeWITH CITY_INFO(stateid ,cityid,districtid,distpt,citypt
(
select stateid ,
cityid,
districtid,
districtpoint as distpt,
COALESCE(citypoint,1,0) as citypt
from dbo.city
where active = 1
and stateid=@stateid and city=@cityid --added
group by stateid ,cityid, districtid
)
update dbo.state_income
set totall_cityinc = case
when isnull(citypt,0) <>0
and isnull(distpt,0) <>0
then (citypt/distpt*100)
else totall_cityinc
end
from dbo.State_Income si --added
INNER JOIN CITY_INFO t1
ON si.StatID = t1.StateID, --added
AND si.CityID = t1.CityID, --added
AND si.DistrictID = t1.DistrictID --added
Hi Jeff - will CTE be fine to use in this context..
Because you used the target of the update in the FROM clause of the joined update, that'll work just fine, Joseph. Nicely done.
--Jeff Moden
Change is inevitable... Change for the better is not.
Viewing 6 posts - 1 through 5 (of 5 total)
You must be logged in to reply to this topic. Login to reply