473,385 Members | 1,890 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

How do I avoid this corelated subquery?

Hello,
I have a situation which would essentially use a co-related subquery.
I am trying to avoid using a co-related subquery due to its slow
performanc and use a join statement instead.

Here is what I am trying to do:

Tables:
========
Limit
-------
RelID ProdID Days Amt1 Amt2
----- ------ ---- ---- ------
148 2 30 15000 30000
148 2 7 1000 2500

Temp Limits
-----------
RelID ProdID MaxDays Amt1 Amt2
----- ------ ----- ------ ------
148 2 1 7500 1000
148 2 7 17500 500
148 2 30 2500 2000
148 2 90 25000 750
148 2 180 7500 -300

I want the totals of Amt1 and Amt2 in the TempLimits table added to
each row in the Limits table where the Days in the Limits Table >=
MaxDays in TempLimits
So, when I run the query with the above data
I need to get

RelID ProdID Days Amt1 Amt2
----- ------ ---- ------ ------
148 2 30 42500 (15000+7500+17500+2500) 33500
(30000+1000+500+2000)
148 2 7 26000 (1000+7500+17500) 4000
(2500+1000+500)

************************************************** **************************
Here is the query that I have right now...

update Limit
set Amt1 = isnull(Amt1,0) + IsNull(temptable.temp_Amt1, 0)
, Amt2 = isnull(Amt2,0) + IsNull(temptable.temp_Amt2, 0)
from Limit inner join
(
select Templimits.relationship_id relationship_id,
Templimits.product_id product_id, sum(Templimits.Amt1) temp_Amt1,
sum(Templimits.Amt2) temp_Amt2
from TempLimits
WHERE TEMPLIMITS.MAXDAYS <= LIMIT.DAYS
group by limit.relationship_id, limit.product_id
) temptable
on Limit.relid = temptable.relid and
Limit.prodid = temptable.prodid

************************************************** ****************************
As you would see here, I am trying to use the condition for Days
(listed in the query in CAPS) inside the inner query which would not
work... Is there any way I can do this apart from using temp tables
and co-related subqueries?

Thanks in advance
Kannan
Jul 20 '05 #1
7 3984
"Kannan" <pv*******@yahoo.com> wrote in message
news:b4*************************@posting.google.co m...
Hello,
I have a situation which would essentially use a co-related subquery.
I am trying to avoid using a co-related subquery due to its slow
performanc and use a join statement instead.

Here is what I am trying to do:

Tables:
========
Limit
-------
RelID ProdID Days Amt1 Amt2
----- ------ ---- ---- ------
148 2 30 15000 30000
148 2 7 1000 2500

Temp Limits
-----------
RelID ProdID MaxDays Amt1 Amt2
----- ------ ----- ------ ------
148 2 1 7500 1000
148 2 7 17500 500
148 2 30 2500 2000
148 2 90 25000 750
148 2 180 7500 -300

I want the totals of Amt1 and Amt2 in the TempLimits table added to
each row in the Limits table where the Days in the Limits Table >=
MaxDays in TempLimits
So, when I run the query with the above data
I need to get

RelID ProdID Days Amt1 Amt2
----- ------ ---- ------ ------
148 2 30 42500 (15000+7500+17500+2500) 33500
(30000+1000+500+2000)
148 2 7 26000 (1000+7500+17500) 4000
(2500+1000+500)

************************************************** **************************
Here is the query that I have right now...

update Limit
set Amt1 = isnull(Amt1,0) + IsNull(temptable.temp_Amt1, 0)
, Amt2 = isnull(Amt2,0) + IsNull(temptable.temp_Amt2, 0)
from Limit inner join
(
select Templimits.relationship_id relationship_id,
Templimits.product_id product_id, sum(Templimits.Amt1) temp_Amt1,
sum(Templimits.Amt2) temp_Amt2
from TempLimits
WHERE TEMPLIMITS.MAXDAYS <= LIMIT.DAYS
group by limit.relationship_id, limit.product_id
) temptable
on Limit.relid = temptable.relid and
Limit.prodid = temptable.prodid

************************************************** ****************************
As you would see here, I am trying to use the condition for Days
(listed in the query in CAPS) inside the inner query which would not
work... Is there any way I can do this apart from using temp tables
and co-related subqueries?

Thanks in advance
Kannan


CREATE TABLE Limits
(
relid INT NOT NULL,
prodid INT NOT NULL,
days INT NOT NULL,
amt1 INT NOT NULL,
amt2 INT NOT NULL,
PRIMARY KEY (relid, prodid, days)
)

CREATE TABLE TempLimits
(
relid INT NOT NULL,
prodid INT NOT NULL,
maxdays INT NOT NULL,
amt1 INT NOT NULL,
amt2 INT NOT NULL,
PRIMARY KEY (relid, prodid, maxdays)
)

UPDATE Limits
SET amt1 = amt1 + (SELECT SUM(amt1)
FROM TempLimits AS TL
WHERE TL.relid = relid AND
TL.prodid = prodid AND
TL.maxdays <= days),
amt2 = amt2 + (SELECT SUM(amt2)
FROM TempLimits AS TL
WHERE TL.relid = relid AND
TL.prodid = prodid AND
TL.maxdays <= days)
WHERE EXISTS (SELECT *
FROM TempLimits AS TL
WHERE TL.relid = relid AND
TL.prodid = prodid AND
TL.maxdays <= days)

--
JAG
Jul 20 '05 #2
Kannan (pv*******@yahoo.com) writes:
************************************************** **************************
Here is the query that I have right now...

update Limit
set Amt1 = isnull(Amt1,0) + IsNull(temptable.temp_Amt1, 0)
, Amt2 = isnull(Amt2,0) + IsNull(temptable.temp_Amt2, 0)
from Limit inner join
(
select Templimits.relationship_id relationship_id,
Templimits.product_id product_id, sum(Templimits.Amt1) temp_Amt1,
sum(Templimits.Amt2) temp_Amt2
from TempLimits
WHERE TEMPLIMITS.MAXDAYS <= LIMIT.DAYS
group by limit.relationship_id, limit.product_id
) temptable
on Limit.relid = temptable.relid and
Limit.prodid = temptable.prodid
************************************************* **************************


I can't see that that query can even compile. You are referring to
limit in the derived table, but I was under the belief that a derived
table cannot refer to tables in the outer part of the query. And in any
case, there are no relid and prodid columns in the derived table temptable.

I would suggest that you post:

o CREATE TABLE and CREATE INDEX statements for your tables.
o The actual query you run.
o The output when you run the UPDATE statement with
SET STATISTICS PROFILE ON.

This makes it a lot easier to give a more accurate response, and relieves
us from what guess what your query actually is.

--
Erland Sommarskog, SQL Server MVP, so****@algonet.se

Books Online for SQL Server SP3 at
http://www.microsoft.com/sql/techinf...2000/books.asp
Jul 20 '05 #3
John Gilson (ja*@acm.org) writes:
UPDATE Limits
SET amt1 = amt1 + (SELECT SUM(amt1)
FROM TempLimits AS TL
WHERE TL.relid = relid AND
TL.prodid = prodid AND
TL.maxdays <= days),
amt2 = amt2 + (SELECT SUM(amt2)
FROM TempLimits AS TL
WHERE TL.relid = relid AND
TL.prodid = prodid AND
TL.maxdays <= days)
WHERE EXISTS (SELECT *
FROM TempLimits AS TL
WHERE TL.relid = relid AND
TL.prodid = prodid AND
TL.maxdays <= days)


John, when you say "TL.relid = relid", does not the prefix-less "relid"
refer to TempLimits?

Also, I am afraid that this is not going to perform overly well, since
SQL Server will resolve the same condition thrice. It is usually better
to have a derived table. If I understand this right it would be:

CREATE TABLE Limits
(
relid INT NOT NULL,
prodid INT NOT NULL,
days INT NOT NULL,
amt1 INT NOT NULL,
amt2 INT NOT NULL,
PRIMARY KEY (relid, prodid, days)
)

CREATE TABLE Templimits
(
relid INT NOT NULL,
prodid INT NOT NULL,
maxdays INT NOT NULL,
amt1 INT NOT NULL,
amt2 INT NOT NULL,
PRIMARY KEY (relid, prodid, maxdays)
)

INSERT Limits VALUES (148, 2, 30, 15000, 30000)
INSERT Limits VALUES (148, 2, 7, 1000, 2500)

INSERT Templimits VALUES (148, 2, 1, 7500, 1000)
INSERT Templimits VALUES (148, 2, 7, 17500, 500)
INSERT Templimits VALUES (148, 2, 30, 2500, 2000)
INSERT Templimits VALUES (148, 2, 90, 25000, 750)
INSERT Templimits VALUES (148, 2, 180, 7500, -300)

UPDATE Limits
SET amt1 = L.amt1 + coalesce(d.amt1, 0),
amt2 = L.amt2 + coalesce(d.amt2, 0)
FROM Limits L
JOIN (SELECT TL.relid, TL.prodid, L1.days,
amt1 = SUM(TL.amt1), amt2 = SUM(TL.amt2)
FROM Templimits TL
JOIN Limits L1 ON L1.relid = TL.relid
AND L1.prodid = TL.prodid
AND TL.maxdays <= L1.days
GROUP BY TL.relid, TL.prodid, L1.days) AS d
ON d.relid = L.relid
AND d.prodid = L.prodid
AND d.days = L.days
go
select * from Limits
go
drop table Limits, Templimits
--
Erland Sommarskog, SQL Server MVP, so****@algonet.se

Books Online for SQL Server SP3 at
http://www.microsoft.com/sql/techinf...2000/books.asp
Jul 20 '05 #4
"Erland Sommarskog" <so****@algonet.se> wrote in message news:Xn********************@127.0.0.1...
John Gilson (ja*@acm.org) writes:
UPDATE Limits
SET amt1 = amt1 + (SELECT SUM(amt1)
FROM TempLimits AS TL
WHERE TL.relid = relid AND
TL.prodid = prodid AND
TL.maxdays <= days),
amt2 = amt2 + (SELECT SUM(amt2)
FROM TempLimits AS TL
WHERE TL.relid = relid AND
TL.prodid = prodid AND
TL.maxdays <= days)
WHERE EXISTS (SELECT *
FROM TempLimits AS TL
WHERE TL.relid = relid AND
TL.prodid = prodid AND
TL.maxdays <= days)
John, when you say "TL.relid = relid", does not the prefix-less "relid"
refer to TempLimits?


Nice catch Erland, yes, those columns not prefixed should refer to the
table to update, Limits, and therefore should be qualified accordingly, e.g.,
TL.relid = Limits.relid.
Also, I am afraid that this is not going to perform overly well, since
SQL Server will resolve the same condition thrice. It is usually better
to have a derived table. If I understand this right it would be:

CREATE TABLE Limits
(
relid INT NOT NULL,
prodid INT NOT NULL,
days INT NOT NULL,
amt1 INT NOT NULL,
amt2 INT NOT NULL,
PRIMARY KEY (relid, prodid, days)
)

CREATE TABLE Templimits
(
relid INT NOT NULL,
prodid INT NOT NULL,
maxdays INT NOT NULL,
amt1 INT NOT NULL,
amt2 INT NOT NULL,
PRIMARY KEY (relid, prodid, maxdays)
)

INSERT Limits VALUES (148, 2, 30, 15000, 30000)
INSERT Limits VALUES (148, 2, 7, 1000, 2500)

INSERT Templimits VALUES (148, 2, 1, 7500, 1000)
INSERT Templimits VALUES (148, 2, 7, 17500, 500)
INSERT Templimits VALUES (148, 2, 30, 2500, 2000)
INSERT Templimits VALUES (148, 2, 90, 25000, 750)
INSERT Templimits VALUES (148, 2, 180, 7500, -300)

UPDATE Limits
SET amt1 = L.amt1 + coalesce(d.amt1, 0),
amt2 = L.amt2 + coalesce(d.amt2, 0)
FROM Limits L
JOIN (SELECT TL.relid, TL.prodid, L1.days,
amt1 = SUM(TL.amt1), amt2 = SUM(TL.amt2)
FROM Templimits TL
JOIN Limits L1 ON L1.relid = TL.relid
AND L1.prodid = TL.prodid
AND TL.maxdays <= L1.days
GROUP BY TL.relid, TL.prodid, L1.days) AS d
ON d.relid = L.relid
AND d.prodid = L.prodid
AND d.days = L.days
go
select * from Limits
go
drop table Limits, Templimits
I like to stick with Standard SQL where possible and stay away from
T-SQL proprietary constructs like this form of UPDATE. However,
one has to be pragmatic and I might give up a little purity if performance
was atrocious.

Staying pure and depending on the data, I might also try:

UPDATE Limits
SET amt1 = amt1 + (SELECT COALESCE(SUM(amt1), 0)
FROM TempLimits AS TL
WHERE TL.relid = Limits.relid AND
TL.prodid = Limits.prodid AND
TL.maxdays <= Limits.days),
amt2 = amt2 + (SELECT COALESCE(SUM(amt2), 0)
FROM TempLimits AS TL
WHERE TL.relid = Limits.relid AND
TL.prodid = Limits.prodid AND
TL.maxdays <= Limits.days)

--
JAG
--
Erland Sommarskog, SQL Server MVP, so****@algonet.se

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

Jul 20 '05 #5
Why not use a function ?

CREATE FUNCTION sumLimitAmt (@Amt_Num int)
RETURNS int
AS
BEGIN
DECLARE @RtnValue int

if(@Amt_Num = 1)

SELECT @RtnValue = SUM(l.amt1)
FROM Limits l
INNER JOIN TempLimits tl
ON (
l.relid = tl.relid AND
l.prodid = tl.prodid
)
WHERE tl.maxdays <= l.days

if(@Amt_Num = 2)

SELECT @RtnValue = SUM(l.amt2)
FROM Limits l
INNER JOIN TempLimits tl
ON (
l.relid = tl.relid AND
l.prodid = tl.prodid
)
WHERE tl.maxdays <= l.days

RETURN(@RtnValue)
END
go

UPDATE Limits
SET amt1 = amt1 + dbo.sumLimitAmt(1),
amt2 = amt2 + dbo.sumLimitAmt(2)
--select dbo.sumLimitAmt(1)
--select dbo.sumLimitAmt(2)
Michael D.
Jul 20 '05 #6
Michael D (so*****@yahoo.com) writes:
Why not use a function ?

CREATE FUNCTION sumLimitAmt (@Amt_Num int)
RETURNS int


I guess since John wanted to stick to standard SQL, that function
are out of the question.

Also, putting a scalar function is definitely not going to address
the performance problem that the original poster appeared to have,
but instead could aggrevate them quite a bit.

--
Erland Sommarskog, SQL Server MVP, so****@algonet.se

Books Online for SQL Server SP3 at
http://www.microsoft.com/sql/techinf...2000/books.asp
Jul 20 '05 #7
Yes.. use of a function is ruled out since it would be a hit on
performance...

I finally had to use a query that was very much similar to the solution
from Erland.

Thanks for all your input, guys.

*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!
Jul 20 '05 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: Haisoo Shin | last post by:
Hello.. I am working on a PHP/PEAR web page that shows statistics of how many people read a certain article during given period of time. I have, say, two tables called 'books' and 'logs'. The...
2
by: lev | last post by:
CREATE TABLE . ( NULL , , (44) ) ID is non-unique. I want to select all IDs where the last entry for that ID is of type 11.
7
by: Andrew Mayo | last post by:
Here's a really weird one for any SQL Server gurus out there... We have observed (SQL Server 2000) scenarios where a stored procedure which (a) begins a transaction (b) inserts some rows into...
5
by: Zero.NULL | last post by:
My multiple level nested corelated query is not fetching correct result. It work fine on small set of data, but fails on larger set of data. Any clue? Explaining data storing and discussing...
0
by: Greg Stark | last post by:
Postgresql 7.4b2 (approximately, compiled out of CVS) When I have a subquery that has a complex subquery as one of the result columns, and then that result column is used multiple times in the...
8
by: Venkata C | last post by:
Hi! Does anyone here know of a way to goad DB2 into converting a correlated subquery to a non-correlated one? Does DB2 ever do such a conversion? We have a query of the form SELECT .. FROM A...
3
by: audj | last post by:
Hello, I am trying to use a subquery to avoid duplicate entries when someone submits a form to subscribe to a mailing list. So I want to check if the email exists before adding the record. ...
5
by: Anne | last post by:
Hello! Here is the statement in question: --STATEMENT A SELECT * FROM dbo.myTable WHERE colX in (SELECT colX FROM dbo.sourceTable) The problem with Statement A is that 'colX' does not exist...
1
by: jcf378 | last post by:
Hi all-- Does anyone have any insight as to how I might create a search form that allows a user to select criteria based on any related table in the whole database. The search form I have now only...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.