Bookmarks

Yahoo Gmail Google Facebook Delicious Twitter Reddit Stumpleupon Myspace Digg

Search queries

dbf2mysql parameter, WWWXXXAPC, wwwxxxAPC, How to unsubscrube from dategen spam, docmd.close 2585, WWWXXXDOCO, nu vot, dhcpd lease file "binding state", WWWXXXDOCO, how to setup procmail to process html2text

Links

XODOX
Impressum

#1: Get rows whose sum matches a value

Posted on 2008-04-17 22:28:16 by Mario Blataric

This should be simple, but I can't work it out without cursors.

I have a table with quantity field. I want to get all first rows
whose sum of quantity matches defined value.

No Quantity
=============
1 50
2 50
3 80
4 80
5 80
6 50

If defined value is, lets say, 180, query should return rows 1..3
Something like
select *
from table
where sum(quantity) = 180
order by No

Any way to work this out?

Thanks,

Mario B.

Report this message

#2: Re: Get rows whose sum matches a value

Posted on 2008-04-17 23:17:23 by Plamen Ratchev

You can accomplish that query without using a cursor. However, performance
will be awful on a large data set.

CREATE TABLE Foo (
nbr INT PRIMARY KEY,
quantity INT);

INSERT INTO Foo VALUES(1, 50);
INSERT INTO Foo VALUES(2, 50);
INSERT INTO Foo VALUES(3, 80);
INSERT INTO Foo VALUES(4, 80);
INSERT INTO Foo VALUES(5, 80);
INSERT INTO Foo VALUES(6, 50);

DECLARE @limit INT;

SET @limit = 180;

SELECT T.nbr, T.quantity, T.running_total
FROM (SELECT A.nbr, A.quantity, COALESCE(SUM(B.quantity), 0)
FROM Foo AS A
LEFT OUTER JOIN Foo AS B
ON A.nbr >= B.nbr
GROUP BY A.nbr, A.quantity
) AS T(nbr, quantity, running_total)
WHERE T.running_total <= @limit
ORDER BY T.nbr;


HTH,

Plamen Ratchev
http://www.SQLStudio.com

Report this message

#3: Re: Get rows whose sum matches a value

Posted on 2008-04-18 08:15:42 by Mario Blataric

Thanks, would never think of that.

When you say performance will be awful, do you mean still faster or
even slower than with cursors?

Thanks,

Mario B.

Report this message

#4: Re: Get rows whose sum matches a value

Posted on 2008-04-18 14:42:41 by Plamen Ratchev

With a large result set this approach will be slower than cursor. To
calculate the running total value it needs to perform (N + N^2)/2 row scans
on the table (where N is the total number of rows). On the other side a
cursor will scan a row only once.

Unfortunately even in SQL Server 2005 the OVER clause for aggregate
functions does not fully support the ANSI OLAP extensions which will allow
us to do things like SUM(quantity) OVER(ORDER BY nbr) which will be a lot
more efficient.

HTH,

Plamen Ratchev
http://www.SQLStudio.com

Report this message

#5: Re: Get rows whose sum matches a value

Posted on 2008-04-18 16:30:28 by Joe Celko

If you can do this on DB2 or another SQL product with full OLAP
functions instead of T-SQL, it is easy:

SELECT X.vague_nbr, X.foo_qty
FROM (SELECT vague_nbr, foo_qty, SUM(foo_qty)
OVER (ORDER BY vague_nbr
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT
ROW))
FROM Foobar
AS X(vague_nbr, foo_qty, running_tot)
WHERE X.running_tot >= 180;

Otherwise, you will have to a self-join that gets to be exponentially
awful as the size of the table increases.

Report this message

#6: Re: Get rows whose sum matches a value

Posted on 2008-04-20 11:37:42 by Mario Blataric

Thanks everyone.

I settled with cursor at the end, since table has near million records
and growing and I'm working with SQL 2005, so other SQL languages are
not an option.

Report this message