View Full Version : Update query


PSL
02-08-2010, 07:47 AM
I have 2 tables

A0505 - 1 record per customer
T0505 - many records per A0505 entry

I need to update the A0505.WIPBal with sum(T0505.Cost) for all A0505 records

I have tried various methids, but none seam to work.

Please advise, what I wish to do is basically

"UPDATE A0505 SET WIPAsAt = SUM(T0505.Cost) WHERE A0505.MattID = T0505.TSAY"

The old way of doing it was create a recordset, then loop through and update each A0505 entry, but this is not fast enough. Code below for reference...

Set RS = PBDbase.OpenRecordset("SELECT TSAY, SUM(COST) FROM T0505 WHERE DATE<= aDate AND (BillNo=0 OR BillDate> aDate) GROUP BY TSAY")
A0505.Index = "MattID"
RS.MoveFirst
RC = 0
While Not RS.EOF
A0505.Seek "=", RS("TSAY")
If Not A0505.NoMatch Then
A0505.Edit
A0505("WIPAsAt") = RS.Fields(1)
A0505.Update
End If
RS.MoveNext
Wend

vbaInet
02-08-2010, 08:03 AM
Do you really have to store that calculated value? It's not advisable to store such values.

If you really want to do this then you can use an UPDATE query.

PSL
02-08-2010, 08:06 AM
I need to store this calculated value, so that it can be displayed in a Crystal report.

Why is it not advisable to store this value?

I am using VB6 as he front end, and these results get updated as a "balance as at" for complex accounting reports everytime they are run

vbaInet
02-08-2010, 08:11 AM
If it can be calculated or generated then there's no need storing the value. However, in your case it seems you are actually doing more with the result.

Have you had a look at how to create an UPDATE query, or is that what you are enquiring about?

PSL
02-08-2010, 08:13 AM
I have tried the update query, but cannot get my head around it, I tried, then found errors, so would appreciate any advice from you guys.

I can add the "where" clause later, as that is related to dates.

Do I need a join of some sort or am I missing the point?

vbaInet
02-08-2010, 08:27 AM
"UPDATE A0505 SET WIPAsAt = SUM(T0505.Cost) WHERE A0505.MattID = T0505.TSAY"


You will need to get that value and put it in there. You can't look it up that way.

PSL
02-09-2010, 12:06 AM
So how would I do it?

JANR
02-09-2010, 01:00 AM
Either create an Update query and run it or in VBA :

Currentdb.Execute "UPDATE A0505....." , dbFailOnError

JR

PSL
02-09-2010, 01:02 AM
It is the update statement which I do not know how to do, that is my question.

I know what I want it to do, but cannot work out how it is written.

JANR
02-09-2010, 01:14 AM
"UPDATE A0505 SET WIPAsAt = SUM(T0505.Cost) WHERE A0505.MattID = T0505.TSAY"

The SUM(T0505.Cost) part has to come from a variabel or a control as vbaInet stated.

so

"UPDATE A0505 SET WIPAsAt = SomeVariabel WHERE A0505.MattID = T0505.TSAY"

I am using VB6 as he front end,

I'm not sure if VB6 and VBA uses similar methode.

JR

PSL
02-09-2010, 01:21 AM
I could use a variable, but this would only be for one at a time. I am already doing this in a loop, but it is inefficient.

I want to be able to update 10,000 A0505.WIPAsAt entries with the total cost of records (possibly 300 for each A0505 record) in one go.

I then need to add dates onto the query.

What I am aiming for is a total cost at a given date of T0505.Cost, where they may have been billed or written off or still as WIP at any date.

(WIP = Work In Progress)

This is what I was thinking on paper...

SQL$ = "UPDATE A0505 SET WIPAsAt = SUM(T0505.Cost) FROM A0505 INNER JOIN T0505 ON A0505.MattID = T0505.TSAY WHERE T0505.DATE<=" & funDtoSQL(aDate) & " AND (T0505.BillNo=0 OR T0505.BillDate>" & funDtoSQL(aDate) & ")"

vbaInet
02-09-2010, 02:01 AM
Right then PSL, let's get you to use the DSum() function. Look it up and see what you can come up with. Syntax afterwards, is:

"UPDATE A0505 SET WIPAsAt = DSum() WHERE A0505.MattID = T0505.TSAY"

PSL
02-09-2010, 02:35 AM
Thanks,

So far I have managed to update ALL A0505 records with the grand total of ALL T0505 records with the followig


UPDATE A0505 SET WIPAsAt = DSum("Cost", "T0505")


So i then try to get it to calc on matching ID's using


UPDATE A0505 SET WIPAsAt = DSum("Cost", "T0505", " WHERE A0505.MattID = T0505.TSAY")


But I get an unknown error

Please advise

vbaInet
02-09-2010, 03:04 AM
Thanks,

UPDATE A0505 SET WIPAsAt = DSum("[Cost]", "T0505", " WHERE A0505.MattID = T0505.TSAY")
But I get an unknown error

Please advise

Goodie. Do you notice anything missing where I've highlighted red? A closing brace maybe:) Post back if you're still struggling.

DCrake
02-09-2010, 03:09 AM
So you are using VB6.

Create a function in an existing or new module

Public Function UpdateWIP()

Dim MyDB As DAO.Database

Dim RsParent As DAO.Recordset
Dim RsChild As DAO.Recordset

Dim SqlP As String
Dim SqlC As String


Set MyDB = OpenDatabase(YourPathAndMdbNameHere)


SqlP = "SELECT Customer, Sum(Nz(Cost,0)) AS SumOfCosts
FROM A0505
GROUP BY Customer
ORDER BY Customer;"

Set SqlP = MyDb.OpenRecordset(SqlP)
Set RsChild = MyDB.OpenRecordset("T0505")

Do Until SqlP.EOF

RsChild.AddNew
RsChild("Customer") = RsParent("Customer")
RsChild("Cost") = RsParent("SumOfCosts")
RsChild.Update
RsChild.Close
RsParent.MoveNext
Loop
RsParent.Close

Set RsParent = Nothing
Set RsChild = Nothing

End Function

This will populate your child table with the sum values of the parent table.

Code is untested and filed names are for brevity only.


David

PSL
02-09-2010, 03:12 AM
OK, now I have

UPDATE A0505 SET WIPAsAt = DSum("Cost", "T0505") WHERE A0505.MattID = T0505.TSAY

But, I get a inpubox asking for T0505.TSAY, Do I need to link these tables using a join, as the database has no linking information

PSL
02-09-2010, 03:13 AM
I have similar code at present (posted previously), but it is inefficient, I must create a single SQL update statement to perform the same process

Thanks anyway



So you are using VB6.

Create a function in an existing or new module

Public Function UpdateWIP()

Dim MyDB As DAO.Database

Dim RsParent As DAO.Recordset
Dim RsChild As DAO.Recordset

Dim SqlP As String
Dim SqlC As String


Set MyDB = OpenDatabase(YourPathAndMdbNameHere)


SqlP = "SELECT Customer, Sum(Nz(Cost,0)) AS SumOfCosts
FROM A0505
GROUP BY Customer
ORDER BY Customer;"

Set SqlP = MyDb.OpenRecordset(SqlP)
Set RsChild = MyDB.OpenRecordset("T0505")

Do Until SqlP.EOF

RsChild.AddNew
RsChild("Customer") = RsParent("Customer")
RsChild("Cost") = RsParent("SumOfCosts")
RsChild.Update
RsChild.Close
RsParent.MoveNext
Loop
RsParent.Close

Set RsParent = Nothing
Set RsChild = Nothing

End Function

This will populate your child table with the sum values of the parent table.

Code is untested and filed names are for brevity only.


David

vbaInet
02-09-2010, 03:19 AM
Save the value of DSum into a variable then perform your update, just to break it down for you.


Dim sumCost as Currency

sumCost = DSum("[Cost]","T0505")

CurrentDb.Execute "UPDATE A0505 SET WIPAsAt = " & sumCost & " WHERE A0505.MattID = T0505.TSAY"


Try that.

PSL
02-09-2010, 03:24 AM
DSum is not defined ...?

Save the value of DSum into a variable then perform your update, just to break it down for you.


Dim sumCost as Currency

sumCost = DSum("[Cost]","T0505")

CurrentDb.Execute "UPDATE A0505 SET WIPAsAt = " & sumCost & " WHERE A0505.MattID = T0505.TSAY"


Try that.

vbaInet
02-09-2010, 03:30 AM
Where are you calling this from? Can you post your db?

PSL
02-09-2010, 03:34 AM
Visual Basic 6, references to DAO 3.51

database contains client data so unable to provide sorry

Where are you calling this from? Can you post your db?

vbaInet
02-09-2010, 03:48 AM
I meant, are you calling it from a module or on a form? Show me the whole function (if it is one) as you have it (including the signature).

PSL
02-09-2010, 03:52 AM
This is a function



UPDATE A0505 SET WIPAsAt = DSum("Cost", "T0505") - works for grand total on each line but not individual

Dim SumCost As Currency
SumCost = DSum("[Cost]", "T0505")

PBDbase.Execute "UPDATE A0505 SET WIPAsAt = " & SumCost & " WHERE A0505.MattID = T0505.TSAY"

vbaInet
02-09-2010, 04:10 AM
Not quite the same line as what I gave:

PBDbase.Execute "UPDATE A0505 SET WIPAsAt = " & SumCost & " WHERE A0505.MattID = T0505.TSAY"
CurrentDb.Execute .....


What do you mean by "but not on idividual"? I thought you wanted the grand total? If you wanted a sum of a specific group, then you include the third paramter in the DSum() function. That acts as a filter.

PSL
02-09-2010, 04:14 AM
PBDBase is the database name we have opened.

I need to calc the total T0505.Cost for each A0505 record, not the grand total of ALL T0505 on every A0505 record.

Each A0505 record has many T0505 records, which I need to update on the database

vbaInet
02-09-2010, 04:25 AM
You don't need that PBDBase line. Just use CurrentDb. Execute is a method of the CurrentDb object.

How is T0505 linked to A0505? Can you provide the (relevant) field names with a record as an example from these tables? E.g.

T0505
-------------------
ID - 7
Cost - 124.95

PSL
02-09-2010, 04:53 AM
OK

A0505 is an account header - 1 per client
T0505 are timesheet records - many per client (A0505 record)

A0505.WIPAsAt should = total of T0505.Cost

There will need to be a date selection on this also, but that can be added in after this initial statement is working.


T0505
-------------------
TSAY - 7 Cost - 124.95
TSAY - 7 Cost - 4.95
TSAY - 7 Cost - 0.95
TSAY - 8 Cost - 50.00
TSAY - 8 Cost - 52.00
TSAY - 9 Cost - 107.54

A0505 (MattID is unique)
-------------------
MattID - 7 WIPAsAt should = £130.85
MattID - 8 WIPAsAt should = £102.00
MattID - 9 WIPAsAt should = £107.54

Many thanks for your help so far

vbaInet
02-09-2010, 06:29 AM
That's not a problem PSL. So at the moment there's no relationship between the two tables? Maybe ClientID? It's either you loop through each client on T0505 adn run the SQL a For statement (for example) or we could look at amending your code so it's more efficient. I noticed you are using the seek method, that can be abit slow. If you want to use sql just let me know and I will write the code that includes the loop and sql string.

PSL
02-09-2010, 06:34 AM
There is no set relationship, all T0505 entries have the same TSAY, which links to the unique A0505.MattID field.

The problem with looping, is we are running the loop 13,000 times (for each A0505 record), but there is 215,000 T0505 records in total, so any SQL statements run slow, this will also be run across users slow networks hence the hoping for a single UPDATE statement

vbaInet
02-09-2010, 06:41 AM
The loop I'm referring to will be run in each record in T0505, not A0505. Sql will handle the updating process in A0505. So in theory, it will run 215,000 times.

PSL
02-09-2010, 06:56 AM
OK, how will that run? What is the alternative to "seek"?

vbaInet
02-09-2010, 08:31 AM
In that case, I've used a combination of DCrake's suggestion with mine. I've amended his code to suit your needs. Double-check before using (and obviously test on your backup copy :))


Dim rs As DAO.Recordset
Dim strSQL As String

strSQL = "SELECT TSAY, Sum(Nz(Cost,0)) AS SumOfCosts FROM T0505 GROUP BY TSAY ORDER BY TSAY;"

Set rs = CurrentDb.OpenRecordset(strSQL)

Do Until rs.EOF
CurrentDb.Execute "UPDATE A0505 SET WIPAsAt = " & !SumOfCosts & " WHERE A0505.MattID = " & !TSAY & ";"
rs.MoveNext
Loop

rs.Close
Set rs = Nothing


Have a go with that.