jwcolby
jwcolby at colbyconsulting.com
Fri Nov 16 09:45:20 CST 2007
By position is brilliant where it will work, which in this specific file (and in most I suspect) it definitely does. Thanks for the idea. I will try to build an Access database with links to the SQL Server BE and test the code to see how fast it is. John W. Colby Colby Consulting www.ColbyConsulting.com -----Original Message----- From: accessd-bounces at databaseadvisors.com [mailto:accessd-bounces at databaseadvisors.com] On Behalf Of A.D.TEJPAL Sent: Friday, November 16, 2007 9:25 AM To: Access Developers discussion and problem solving Cc: A.D.TEJPAL Subject: Re: [AccessD] merging records You are welcome John! I have since optimized the subroutine still further. Taking into account the point raised by you, iteration through fields is now implemented based upon their number position. This eliminates the repeated check against InStr() function for excluding initial set of fields (not directly representing survey response). Instead, the loop starts at first survey field. In the sample case, position of this field, represented by constant PosOfFirstSurveyField is 5. You can substitute this figure by an appropriate value as required. Two versions of the optimized subroutine have been made out, one uses append query for final insertion, while the other depends upon recorset's AddNew method as suggested by Gustav. The first routine, named P_PopulateResultTableByAppQry() is placed below. The other one, named P_PopulateResultTableByRecordset() shall be sent by subsequent post, so as to avoid crossing the max size prescribed by the moderators. Best wishes, A.D.Tejpal ------------ Sample subroutine - for merging survey results T_data is source table. Compacted results (ignoring blanks) are appended to T_Result. '==================================== Sub P_PopulateResultTableByAppQry() ' This subroutine merges the survey ' results (ignoring blanks) for each person in source ' table T_Data and appends the compacted outcome ' into destination table T_Result. Structure of T_Result ' is identical to that of T_Data ' T_Dummy is a single field single record table. Dim Qst As String, Txt As String Dim Fnm As String, Qst2 As String Dim Cnt As Long Dim rst1 As DAO.Recordset Dim rst2 As DAO.Recordset Dim tdf As TableDef Dim db As DAO.Database Const SourceTable As String = "T_Data" Const DestnTable As String = "T_Result" Const DummyTable As String = "T_Dummy" Const PosOfFirstSurveyField As Long = 5 Set db = DBEngine(0)(0) ' Clear destination table db.Execute "DELETE FROM " & _ DestnTable & ";", dbFailOnError Qst = "SELECT FirstName, LastName, " & _ "Address FROM " & SourceTable & _ " GROUP BY FirstName, " & _ "LastName, Address;" Set rst1 = db.OpenRecordset(Qst) Set tdf = db.TableDefs(SourceTable) Do Until rst1.EOF ' Build first part of SQL for appending Person ' and address particulars Qst = "INSERT INTO " & DestnTable & _ " SELECT '" & _ rst1.Fields("FirstName") & "' AS " & _ "FirstName, '" & rst1.Fields("LastName") & _ "' AS LastName, '" & rst1.Fields("Address") & _ "' AS Address," ' Build balance portion of SQL for appending ' survey results (ignoring blanks), field-wise For Cnt = (PosOfFirstSurveyField - 1) _ To (tdf.Fields.Count - 1) Fnm = tdf.Fields(Cnt).Name Qst2 = "SELECT " & Fnm & _ " FROM " & SourceTable & _ " WHERE FirstName = '" & _ rst1.Fields("FirstName") & _ "' AND LastName = '" & _ rst1.Fields("LastName") & _ "' AND Address = '" & _ rst1.Fields("Address") & _ "' AND Len(" & Fnm & ") > 0;" Set rst2 = db.OpenRecordset(Qst2) ' This If/End If block is meant to prevent ' error (no current record) if rst2 is empty If rst2.RecordCount > 0 Then Qst = Qst & " '" & rst2.Fields(0) & _ "' AS " & Fnm & "," End If Next ' Remove trailing comma Qst = Left(Qst, Len(Qst) - 1) Qst = Qst & " FROM " & DummyTable & ";" ' Append to destination table db.Execute Qst, dbFailOnError rst1.MoveNext Loop rst1.Close rst2.Close Set rst1 = Nothing Set rst2 = Nothing Set tdf = Nothing Set db = Nothing End Sub '==================================== ----- Original Message ----- From: jwcolby To: 'Access Developers discussion and problem solving' Sent: Friday, November 16, 2007 00:57 Subject: Re: [AccessD] merging records A.D. I will get around to this, just not sure when. Running this through Access / VBA is probably a non starter since not only are there a lot of fields (>600), but also a lot of records (>50 million). Thus if this is ever to actually work it will need to be done in VB.Net. My experience so far is that VB.Net speeds things up by a factor of 10 or more. Even then I would suggest something like pulling the field names that will be actually used out and placing them (or maybe their numeric field position in the record object) in a collection. That way the code that iterates the fields becomes a simple "for each in colValidFld" construct instead of a constant comparison to see if they are in the string of non-valid fields. If you place the valid field names in the collection, then the For Each loop would "just have" the field names to build up the SQL statement. Additionally I think you can use the field names to index into the field collection to extract the values: rst.fields(strFldName).value Believe me, with 600 fields and 50 million records, it needs all the efficiency it can get. And BTW thanks for the code. John W. Colby Colby Consulting www.ColbyConsulting.com -- AccessD mailing list AccessD at databaseadvisors.com http://databaseadvisors.com/mailman/listinfo/accessd Website: http://www.databaseadvisors.com