469,926 Members | 1,526 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,926 developers. It's quick & easy.

Re-using a calculated sub-select field in a view?

RCS
I've been running into more and more complexity with an application, because
as time goes on - we need more and more high-level, rolled-up information.
And so I've created views, and views that use other views.. and the queries
are getting slower and slower.

This morning, I'm working on something like this:

select
<some columns>,
"calculatedcolumn" = (select top 1 crap from stuff where
thingy='whatchamacallit')
from
someview

now, I realized that I need to really return "calculatedcolumn" in a couple
other places in the select like this - well, this is what I WANT to do:
select
<some columns>,
calculatedcolumn = (select top 1 crap from stuff where
thingy='whatchamacallit'),
otherfield = case SomeBit
when 1 then calculatedcolumn
else count(somefield)
end,
otherfield1 = case SomeotherBit
when 1 then calculatedcolumn
else sum(somefield)
end,
otherfield2 = case SomeBit2
when 1 then calculatedcolumn
else avg(somefield)
end,
otherfield3 = case SomeBit3
when 1 then calculatedcolumn
else count(somefield)
end,
from
someview

Point is, I CAN'T do that, so I have to re-run that sub-select for EACH of
these cases, and that is KILLING this stored procedure. It seems to me, that
if the database when and already got that field, for that row - I should be
able to re-use, rather than going back out additional times.

Is there a way to so this? Put simpler:

select
x = (select top 1 user_id from users),
bestUser=x,
smartestUser=x
from
Users

can I re-use "x" in that example. Thanks!
Jul 23 '05 #1
6 2625
RCS (rs****@gmail.com) writes:
Is there a way to so this? Put simpler:

select
x = (select top 1 user_id from users),
bestUser=x,
smartestUser=x
from
Users

can I re-use "x" in that example. Thanks!


Maybe. It depends a little what is in that subquery. If it's uncorrelated
to the main query, you could to:

SELECT x.x, bestUser = CASE WHEN ... THEN x ELSE NULL END, ...
FROM users
CROSS JOIN (SELECT TOP 1 user_id FROM users ORDER BY somecol) AS x

Here I'm using a derived table. A derived table is kind of a temp table
in the middle of the query. However, it is never materialized, and SQL
Server may not even compute the table as such, but can recast computation
order as result is the same.
--
Erland Sommarskog, SQL Server MVP, es****@sommarskog.se

Books Online for SQL Server SP3 at
http://www.microsoft.com/sql/techinf...2000/books.asp
Jul 23 '05 #2
RCS
Thanks for the response!

In this particular case, the general gist is that this is for tracking
scores for tests.. the outer select is for general information (module name,
etc) and the subselects are tallying up total users, how many passed, how
many failed.. so in psuedo sql, it's something like this (this is very, very
over-simplied - but hopefully is clear):

select
modulename,
totalusers = (select count(*) from moduleusers where moduleid =
m.moduleid),
passed = (select count(distinct userid) from modulescores where
moduleid=m.moduleid and didpass=1)
from module as m

but it gets more complicated, I have to add some logic in for several fields
that say "if the module is a training module, then return back 'totalusers'
becuase even just finishing a practice module, should be considered
'passing'". For example.. So what I am doing now (using the same example
above) is:

select
modulename,
totalusers = (select count(*) from moduleusers where moduleid =
m.moduleid),
passed = case moduleistraining
when 1 then (select count(*) from moduleusers where moduleid =
m.moduleid) -- this is the same as "totalusers" above
else (select count(distinct userid) from modulescores where
moduleid=m.moduleid and didpass=1)
end
from module as m

But that "(select count(*) from moduleusers where moduleid = m.moduleid)"
(again, as a simple example) is in real life, a complex join, to a couple of
views and is slow - and I have to keep re-using it in other select fields.

I've never had a use for, or maybe never understood the "cross join"
statment - and I'm not clear on how you mean to use it below. Could you
elaborate?? Thanks again!!
"Erland Sommarskog" <es****@sommarskog.se> wrote in message
news:Xn**********************@127.0.0.1...
RCS (rs****@gmail.com) writes:
Is there a way to so this? Put simpler:

select
x = (select top 1 user_id from users),
bestUser=x,
smartestUser=x
from
Users

can I re-use "x" in that example. Thanks!


Maybe. It depends a little what is in that subquery. If it's uncorrelated
to the main query, you could to:

SELECT x.x, bestUser = CASE WHEN ... THEN x ELSE NULL END, ...
FROM users
CROSS JOIN (SELECT TOP 1 user_id FROM users ORDER BY somecol) AS x

Here I'm using a derived table. A derived table is kind of a temp table
in the middle of the query. However, it is never materialized, and SQL
Server may not even compute the table as such, but can recast computation
order as result is the same.
--
Erland Sommarskog, SQL Server MVP, es****@sommarskog.se

Books Online for SQL Server SP3 at
http://www.microsoft.com/sql/techinf...2000/books.asp

Jul 23 '05 #3
RCS (rs****@gmail.com) writes:
select
modulename,
totalusers = (select count(*) from moduleusers where moduleid =
m.moduleid),
passed = case moduleistraining
when 1 then (select count(*) from moduleusers where moduleid =
m.moduleid) -- this is the same as "totalusers" above
else (select count(distinct userid) from modulescores where
moduleid=m.moduleid and didpass=1)
end
from module as m

SELECT m.modulname, mu.totalusres,
passed = CASE m.moduleistraing
WHEN 1 THEN mu.totalusrers
ELSE ms.didpass
END
FROM modules m
JOIN (SELECT moduleid, totalusers = COUNT(*)
FROM moduleusers
GROUP BY moduleid) mu ON m.moduleid = mu.moduleid
JOIN (SELECT moduleid, didpass = COUNT(DISTINCT userid
FROM modulescores
WHERE didpass = 1
GROUP BY moduleid) AS ms ON m.moduleid = ms.moduleid

See my preivious post for the explanation of the derived tables.
I've never had a use for, or maybe never understood the "cross join"
statment - and I'm not clear on how you mean to use it below. Could you
elaborate?? Thanks again!!


A cross join gives all possible combinations; this is the famous
"carteisan product". I used a cross join this case because that was
how I could translate your very loose example.

--
Erland Sommarskog, SQL Server MVP, es****@sommarskog.se

Books Online for SQL Server SP3 at
http://www.microsoft.com/sql/techinf...2000/books.asp
Jul 23 '05 #4
RCS
Ah-HA!!! Very nice - thanks very much!!!

"Erland Sommarskog" <es****@sommarskog.se> wrote in message
news:Xn**********************@127.0.0.1...
RCS (rs****@gmail.com) writes:
select
modulename,
totalusers = (select count(*) from moduleusers where moduleid =
m.moduleid),
passed = case moduleistraining
when 1 then (select count(*) from moduleusers where moduleid =
m.moduleid) -- this is the same as "totalusers" above
else (select count(distinct userid) from modulescores where
moduleid=m.moduleid and didpass=1)
end
from module as m

SELECT m.modulname, mu.totalusres,
passed = CASE m.moduleistraing
WHEN 1 THEN mu.totalusrers
ELSE ms.didpass
END
FROM modules m
JOIN (SELECT moduleid, totalusers = COUNT(*)
FROM moduleusers
GROUP BY moduleid) mu ON m.moduleid = mu.moduleid
JOIN (SELECT moduleid, didpass = COUNT(DISTINCT userid
FROM modulescores
WHERE didpass = 1
GROUP BY moduleid) AS ms ON m.moduleid = ms.moduleid

See my preivious post for the explanation of the derived tables.
I've never had a use for, or maybe never understood the "cross join"
statment - and I'm not clear on how you mean to use it below. Could you
elaborate?? Thanks again!!


A cross join gives all possible combinations; this is the famous
"carteisan product". I used a cross join this case because that was
how I could translate your very loose example.

--
Erland Sommarskog, SQL Server MVP, es****@sommarskog.se

Books Online for SQL Server SP3 at
http://www.microsoft.com/sql/techinf...2000/books.asp

Jul 23 '05 #5
It's difficult to understand what you are really trying to do, but if
calculatedcolumn is going to be the same all the way through, DECLARE
and SET it upfront, i.e.
DECLARE @CalculatedColumn int <or whatever>
SET @CalculatedColumn = (select top 1 crap from stuff where
thingy='whatchamacallit')

then every time you need it again, just put @CalculatedColumn instead
of the whole statement that figures it out.

Jul 23 '05 #6
A variable could be used if you know the result is going to be static.

I've also run into a problem similar to this when updating a table
with calculations, but when the calculations are based off the current
row it's updating the use of a variable gets thrown out the window :(
I had to keep reselecting the result, a correlated sub-query really,
but with my update statement I used it a hell of a lot and a simple
update statement grew to over 300 lines :)

But hey, with a cursor it took 40 mins with 1.5 million rows, now it
takes 5 mins :)

I'm going to take a look into that derived table example, might be
able to speed my statements up! Cheers!

Ian
"Ellen K" <ek*******@yahoo.com> wrote in message news:<11**********************@f14g2000cwb.googleg roups.com>...
It's difficult to understand what you are really trying to do, but if
calculatedcolumn is going to be the same all the way through, DECLARE
and SET it upfront, i.e.
DECLARE @CalculatedColumn int <or whatever>
SET @CalculatedColumn = (select top 1 crap from stuff where
thingy='whatchamacallit')

then every time you need it again, just put @CalculatedColumn instead
of the whole statement that figures it out.

Jul 23 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

1 post views Thread by Nel | last post: by
4 posts views Thread by Craig Bailey | last post: by
11 posts views Thread by James | last post: by
4 posts views Thread by Alan Walkington | last post: by
1 post views Thread by John Ryan | last post: by
8 posts views Thread by Beowulf | last post: by
1 post views Thread by Clarice Almeida Hughes | last post: by
2 posts views Thread by JW | last post: by
2 posts views Thread by Frans Schmidt | last post: by
2 posts views Thread by sky2070 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.