views:

32

answers:

2

I have been trying to search for this and am not sure I am using the correct terms. Or it might just be that it's not possible. But what I am trying to do is update all records in a table that make up a sum value that is less than a set value.

So here is an example:

ID type amount received_date processed_date
1 debit 10 7/1/2010 NULL
2 debit 10 7/2/2010 NULL
3 debit 10 7/3/2010 NULL

Now what I want to do is update all records that are equal to a sum of less than 22. So when I would do the sum id 1 and 2 would equal 20 which is less than 22. But it also needs to be only records that have a null for processed_date. I also want it to work so that it updates from oldest to newest.

Basically here is how I would write it in pseudo code:

UPDATE credits
SET date_processed = '8/1/2010'
WHERE SUM(amount) <= @total AND
    credit_type = [debits]

But I know that this doesn't work. So I'm hoping some SQL master might have ideas.

I'm sure I could write this within a cursor but I'm wondering if there is a set based way to perform this.

EDIT: I updated the table and brief description below to better portray my circumstance.

+1  A: 

You should use the HAVING clause for this type of situations.

According to w3schools, "The HAVING clause was added to SQL because the WHERE keyword could not be used with aggregate functions."

UPDATE credits
SET date_processed = '8/1/2010'
WHERE credit_type = [debits]
HAVING SUM(amount) <= @total 

Here is a great tutorial found on w3schools

http://www.w3schools.com/SQL/sql_having.asp

Ranhiru Cooray
Thanks let me check this out. I wasn't sure about having.
spinon
When I try this I get an incorrect syntax near having? Any ideas? I will look some more myself as well.
spinon
Ok no go on this. HAVING can be used only with the SELECT statement. That is straight out of the MSDN documentation.
spinon
Please post the code you have tried so me or someone can see what is wrong :)
Ranhiru Cooray
What code? I copied what you have there and changed to match my fields. But I was getting an incorrect syntax error. So I looked up having in msdn documentation for sql and it said having is only available for select statements. Here is the link: http://msdn.microsoft.com/en-US/library/ms180199(v=SQL.90).aspxIt's in the first paragraph.
spinon
@spinon: Yes. You are correct. Let me see if I can fix this using only a WHERE clause.
Ranhiru Cooray
+2  A: 

Rows in a SQL table, represent an unordered list of items. Thus, we have to provide an order. In your example, you hint that it should process the rows ordered by Id.

Update TableName
Set processed_date = '2010-08-01'
Where [type] = 'debit'
    And Exists      (
                    Select 1
                    From TableName As C1
                    Where C1.Id <= TableName.Id
                        And C1.[type] = 'debit'
                    Having Sum(C1.amount) <= @total
                    )

As I mentioned in comments, it is not safe to depend on Id being the marker for sequence. It is possible to have gaps and for someone to insert "later" rows into those gaps using IDENTITY_INSERT. Instead, you should use a datetime column. If that column is received_date, then simply substitute Id for received_date in the above query.

Thomas
I have an order setup so I am not worried about that. I just cut that out for brevity. But you are thinking that I just figured out. Here is what I came up with: UPDATE credits SET date_processed = '8/1/2010' WHERE id IN ( SELECT id FROM credits WHERE credit_type = [debits] GROUP BY id HAVING ABS(SUM(amount)) <= @total )
spinon
Thomas I was just about to answer my own question but I feel like a dork when I do that so I'm glad you submitted this. Now I don' have to.
spinon
Yours is actually better because I was grouping on the id which was actually not exactly correct because it was grouping per record. Yours will do the grouping correctly.
spinon
@Thomas I feel this is close but it's still not correct. After closer inspection I think I am still seeing a problem. Not sure why but when I run I get no results. So let me update my question with a little more detail since it seems like I need it.
spinon
@spinon - It worked for me. I'll update my query based on new info. I will say that it is dangerous to rely on Id being the sequential marker for the rows. If possible, received_date would be better.
Thomas
@Thomas I agree received date is the way I would like to go not id
spinon
@Thomas thanks a million for this query. It worked perfect. Exaclty what I was hoping to do.
spinon