tags:

views:

650

answers:

2

How to do query and display the records until it reaches a certain number?

Suppose you want to select student until the total sum of the student's money reaches 1000?

Addition

 Student ID   Student Name   Student Money 
 ---------    -----------     --------------
   1           John            190
   2           Jenny           290
   3           Ben             200
   4           Andy            120
   5           Lynna           300

If I wanna stop at 500, I would get record number 1 and 2 (190 + 290). If I wanna stop at 1000, I would get record 1 until 4.

+1  A: 

There is no "intrinsic" order to a SQL table, so you'll have to specify some ORDER BY clause to give that "until" phrase any meaning. Given that, the sum of the ``first'' N records can be obtained with a SELECT SUM(money) FROM student ORDER BY xxx LIMIT N. Using an auxiliary table INTS which has integers in natural order, you can find the maximum suitable N by something like:

SELECT MAX(N) FROM INTS
WHERE (SELECT SUM(money) FROM student ORDER BY xxx LIMIT N) < 1000

and finally insert this as another nested SELECT for the LIMIT clause in your overall SELECT. All of this smells like it would be rather inefficient, though! As often when nested SELECTs seem too many and too slow, an alternative is doing this in steps: first build a temporary table with the "progressive sums", then use that to help you find the limit you need.

Alex Martelli
i think LIMIT N would only limit number of records, can it place limit on the sum itself?
henry
right, the WHERE (SELECT SUM ...) < 1000 is there to determine the appropriate N based on the limit on the sum.
Alex Martelli
wow.. you enlightened me.
henry
so for example with the table example you now added, the auxiliary table could be built by `SELECT S1.Id, SUM(S2.Money) FROM Student S1, Student S2 WHERE S2.Id <= S1.Id` (implicitly ordering by Id).
Alex Martelli
A: 

Oops ... MySQL ... this solution is for MS SQL ...

Here is a solution using the ROW_NUMBER() function.

SELECT Student.*, SUM(StudentBefore.Money) AS AccumulatedMoney  
FROM (  
       SELECT *, ROW_NUMBER() OVER(ORDER BY Id) AS RowNumber  
       FROM Students  
     ) AS Student  
     INNER JOIN  
     (  
       SELECT *, ROW_NUMBER() OVER(ORDER BY Id) AS RowNumber  
       FROM Students  
     ) AS StudentBefore  
     ON StudentBefore.RowNumber <= Student.RowNumber  
GROUP BY Student.RowNumber, Student.Id, Student.Name, Student.Money  
HAVING SUM(StudentBefore.Money) < 1000

The execution plan indicates that sorting the table is the most expensive operation. If there is an index on the columns to sort by - you example indicates you want to sort by the primary key id - the index scan will become the most expensive operation.

Daniel Brückner
He needs a MySQL solution.
Ionuț G. Stan