Access query or VBA code to move data from one table to another depending on first row unique identifier - sql

Is it possible to write a query to loop through the rows of a two column table, checking the first column for a certain identifier and copy the data in the second column into a new table?
Example:
tblSurveyData
FirstColumn Second Column
A0 John
A2 Smith
A3 05-01-1973
tblSurveyReport
FirstName MiddleName LastName DateOfBirth
John Smith 05-01-1973
Where A0 data would go to FirstName, A1 MiddleName, A2 LastName and A3 DateOfBirth. There are many more identifiers and fields but just as an example how would you do this with a query in Access or is VBA a better solution?
The only solution I came up with is the following VBA but this bypasses the two column table and tries to insert into the tblSurveyReport table. Unfortunately, it puts each piece of data into its own row which doesn't help.
If Identifier = "A0" Then
DoCmd.RunSQL "INSERT INTO tblSurveyReport " _
& "(FirstName) " _
& "VALUES ('" & Info & "')"
ElseIf Identifier = "A1" Then
DoCmd.RunSQL "INSERT INTO tblSurveyReport " _
& "(MiddleName) " _
& "VALUES ('" & Info & "')"
ElseIf Identifier = "A2" Then
DoCmd.RunSQL "INSERT INTO tblSurveyReport " _
& "(LastName) " _
& "VALUES ('" & Info & "')"
ElseIf Identifier = "A3" Then
DoCmd.RunSQL "INSERT INTO tblSurveyReport " _
& "(DateOfBirth) " _
& "VALUES ('" & Info & "')"
End If
However each piece of data is going into its own row and I need it all in the same row.
Any help is greatly appreciated.
Thanks in advance.
TC

Use INSERT INTO with a SELECT statement
INSERT INTO tblSurveyReport(FirstName) SELECT FirstName FROM tblSurveyData where FirstColumn = 'A0'
INSERT INTO tblSurveyReport(MiddleName) SELECT MiddleName FROM tblSurveyData where FirstColumn = 'A1'
You could run this using a DoCmd, as a query in Access, etc.

You will need something that would link your records together. What happens if the data gets re-sorted? How would you know that all the info in your example should be in the same record? I believe the only way to do something like this would be to create a 3rd field in your first table that determines which data belongs with which, something like a UserID. Then the table would look like this:
tblSurveyData
FirstColumn Second Column UserID
A0 John XX001
A2 Smith XX001
A3 05-01-1973 XX001
Then you could create a preliminary query like:
Select DISTINCT UserID from tblSurveyData
Use that as your "pointer" query and loop through the results, and then you can pull all the records with each UserID out and copy them into the new table. Or, you can inner join the "pointer" query and tblSurveyData, and then use a Crosstab query. The easiest way to do that would be to use the wizard to create it, and then just copy the code into your VBA.
EDIT: For easier readability for future readers, the SQL for the query you're asking for in your comment is:
SELECT Max(IIf([Identifier]="A0",[IValue],"")) AS FName, Max(IIf([Identifier]="A1",[IValue],"")) AS MName, Max(IIf([Identifier]="A2",[IValue],"")) AS LName, Max(IIf([Identifier]="A3",[IValue],"")) AS BDate FROM tblSurveyData;
You will need to change "First Column" in your sample data to "Identifier", and "Second Column" to "IValue" (or make the corresponding field name changes to the above SQL). I have tested this and it worked perfectly, giving you one record with all 4 values in corresponding fields. Once you've pasted that into a blank query, you can switch to Design View and change the query to an Append or MakeTable query and that will let you export the results to tblSurveyReport.

You could have simply two recordsets, like this:
1st recordset: rsSurveyData
2nd recordset: rsSurveyReport
The idea is to browse the first recordset along its records, and the second along its fields.
depending on the recordset object you are using (DAO or ADODB), the opening syntax will be slightly different, but you'll find all details in the help. I am using here the ADODB syntax for the 'Find', 'Move', and 'Update' methods. DAO recordsets need an extra 'Edit' method before changing the data. And I do not remember if the fields collection of the recordset object is indexed from 0 or 1 ...
Then:
rsSurveyData.moveFirst
rsSurveyReport.Find "FirstName ='" & rsSurveyData.fields("A0") & "'"
if rsSurveyReport.EOF then
'do what you have to do when the record does not exist, for example:'
rsSurveyReport.addNew
rsSurveyreport.fields(1) = rsData.fields(1)
Else
'you''ve just found the record that needs to be updated'
for i = 2 to rsSurveyData.recordcount
rsSurveyData.move i, 1
rsSurveyReport.fields(i)=rsSurveyData.fields(1)
next i
rsSurveyReport.update
Endif

Related

Outputting the result of an SQL query into a text box

I'm creating a form that displays information about an individual that is taken from two tables when a name is entered by the user. I want the fields to be output into they're own text boxes. My code looks similar to what's below.
When I run the code it displays the literal query "SELECT name etc..." in the textbox. I saw Dlookup works for textboxes but to my understanding it doesn't work well with more than one table. Any advice would be greatly appreciated!
PS I'm a VBA/access newbie
Dim SQL, SearchInput As String
SQL = "SELECT name" & _
"FROM tablename INNER JOIN othertablename ON tablename.name = othertablename.name" & _
"WHERE tablename.name LIKE ""*" & SearchInput & "*""
Me.txtbox = SQL
I'm pretty sure this is a duplicate, but it's faster to answer than hunt for the other posts.
You need to declare a recordset and assign the data returned from the select statement to it. This will leave you with something very similar to an array. After that you need to just line up the array element to the positions of the columns. IE. rs(0)=name in the select statement above.
Dim rs As Recordset
Dim SQL As String, SearchInput As String
SQL = "SELECT name " & _
"FROM tablename INNER JOIN othertablename ON tablename.name = othertablename.name " & _
"WHERE tablename.name LIKE ""*" & SearchInput & "*""
Set rs = CurrentDb.OpenRecordset(strSQL, dbOpenSnapshot)
Me.txtBox = rs(0)
That should work.
Since you are new to MS Access & VBA in general, I'll propose a solution which avoids VBA entirely.
In your current code, I assume that SearchInput is sourcing its value from another control on your form.
I would suggest creating a new saved query (called it MyQuery) with the following SQL:
select table2.name from table1 inner join table2 on table1.name = table2.name
Then, in the Control Source for your textbox, use a DLookup expression with the following arguments:
=dlookup("[name]", "MyQuery", "table1.name like '*" & [SearchInput] & "*'")
Here, [SearchInput] refers to the name of the control on your form containing the search criteria.

MS Access Using ComboBox Value in SQL Field

Trying to set up a query where one of the fields is selected by the value in a combobox. Can't figure out the right syntax. I'm in the SQL view of the query builder, using the following:
SELECT Deviations.Deviation, Deviations.Rev, Deviations.Title, Deviations.Issued, Deviations.ExpiryDate, Deviations.ExpiryHours, Deviations.ExpOther, Deviations.Active, Deviations.[Forms]![DeviationSelectionForm]![cmbAircraft]
FROM Deviations
WHERE Deviations.[Forms]![DeviationSelectionForm]![cmbAircraft]=True
ORDER BY Deviations.Deviation DESC
The combo box selects the tail number of the aircraft which is a checkbox in the table. There are multiple aircraft tail numbers as checkbox fields. So if there were no combobox and I wanted the query to use as example aircraft 416, the query would be:
SELECT Deviations.Deviation, Deviations.Rev, Deviations.Title, Deviations.Issued, Deviations.ExpiryDate, Deviations.ExpiryHours, Deviations.ExpOther, Deviations.Active, Deviations.[416]
FROM Deviations
WHERE Deviations.[416]=True
ORDER BY Deviations.Deviation DESC
When I test this query it works as I need it to.
So the question is how to I create the query with the combobox in a form identifying the field name of a table?
Build the Query SQL viacode in the combobox afterUpdate event.
Dim strSql as String
strSql = "SELECT Deviations.Deviation, Deviations.Rev, Deviations.Title, Deviations.Issued, " _
& "Deviations.ExpiryDate, Deviations.ExpiryHours, Deviations.ExpOther, " _
& "Deviations.Active, Deviations." & Me!cmbAircraft _
& " FROM Deviations " _
& "WHERE Deviations." & Me!cmbAircraft & " =True " _
& "ORDER BY Deviations.Deviation DESC"
CurrentDb.QueryDefs(<yourqueryname>).SQL = strSql
That said, it seems like you have built a spreadsheet instead of a database.
Your tables are not normalized. Aircraft should be records, not columns. I suggest you read up on database design and normalization.

How do I access multiple records from the same table using SQLDataAdapter?

This almost works. I get an error at the last line that looks like it's complaining about the C1 reference. Is there a simple way around this? There is nothing wrong with the query or connection.
Dim CmdString As String
Dim con As New SqlConnection
Try
con.ConnectionString = PubConn
CmdString = "select * from " & PubDB & ".dbo.Suppliers as S " & _
" join " & PubDB & ".dbo.Address as A" & _
" on S.Supplier_Address_Code = A.Address_IDX" & _
" join " & PubDB & ".dbo.Contacts as C1" & _
" on S.Supplier_Contact1 = C1.Contact_IDX" &
" join " & PubDB & ".dbo.Contacts as C2" & _
" on S.Supplier_Contact2 = C2.Contact_IDX" &
" WHERE S.Supplier_IDX = " & LookupIDX
Dim cmd As New SqlCommand(CmdString)
cmd.Connection = con
con.Open()
Dim DAdapt As New SqlClient.SqlDataAdapter(cmd)
Dim Dset As New DataSet
DAdapt.Fill(Dset)
con.Close()
With Dset.Tables(0).Rows(0)
txtAddress1.Text = .Item("Address1").ToString
txtAddress2.Text = .Item("Address2").ToString
txtSupplierName.Text = .Item("Address_Title").ToString
txtAttn.Text = .Item("Attn").ToString
txtBusinessPhone1.Text = .Item("C1.Contact_Business_Phone").ToString
You would not include the "C1" table alias as part of your column name. It will be returned from your query as Contact_Business_Phone.
For accessing multiple rows you could use the indexer as you are in the example above "Rows(0)" by placing your With block into a For loop and accessing the "Rows(i)" with your loop variable. However, this would not help much as your are assigning this to individual text boxes, so you'd only see the last value on your page/screen.
The alias C1 is used by SQL Server and is not persisted to the result set. Have you taken this query into SQL Management Studio to see the results?
Since you requested all columns (*) and joined to the Contacts table twice, you'll end up with duplicate column names in the result. For example, if the Contacts table has a LastName field, you'll end up with TWO LastName columns in your result.
I haven't tried to duplicate this in my local environment, but I can't imagine the data adapter is going to like having duplicate column names.
I recommend specifically including the columns you want to return instead of using the *. That's where you'll use the alias of C1, then you can rename the duplicate columns using the AS keyword:
SELECT C1.LastName AS [Supplier1_LastName],
C2.LastName AS [Supplier2_LastName],
...
This should solve your problem.
Good Luck!
You should only be pulling back the columns that you're in fact interested in, as opposed to *. It's sort of hard to tell exactly what data exists in which tables since you're pulling the full set, but at a quick guess, you'll want in your select statement to pull back A.Address1, A.Address2, A.AddressTitle, ?.Attn (not sure which table this actually derives from) and C1.Contact_Business_Phone. Unless you actually NEED the other fields, you're much better off specifying the individual fields in your query, besides having the possible duplicate field issue that you're running into here, it can also be a significant performance hit pulling everything in. After you clean up the query and only pull in the results you want, you can safely just reference them the way you are for the other fields, without needing a table alias (which as others have pointed out, isn't persisted to the result set anyways).

How would I use excel to generate a large update sql statement?

I know there's a way to have insert statements within excel. Is there one for update? so far I've managed to come up with my update statement in SQL, but I have 6000 rows to update:
= "Update table Set name = " & A1 & " Where namefk = " & E2 & ""
Basically, I want the name and namefk to be populated with fields in my excel..but I can't seem to get it right. Any help will be appreciated.
= "update table set name = '" & B1 & "' where namefk = '" & A1 & "'"
where column A1 has name fk & B1 have name
You can drag the formula to achieve query to update thousands of records :)
You can look into the link with the
Example excel
Hope it helps
=CONCATENATE("update Site set SiteName='",D13,"' where Place='",A13,"' and Code='",B13,"'")
As per above we can make update query dynamically and if we make for one row after that we need to drag down, so automatically it will take column values.

How to "order by" a column and "Include Column Name with query"?

I am trying to run a sql query in excel and I want to :
1. order the query result by my column "Stationname"
2. include the column names with the query
Right now it is returning all the columns without the column name, and the end users do not know what it is.
Could someone please help? I am stuck! Below is my current code:
strQuery = "select pipelineflow.lciid lciid, ldate, volume, capacity, status, " & _
"pipeline, station, stationname, drn, state, county, owneroperator, companycode, " & _
"pointcode, pointtypeind, flowdirection, pointname, facilitytype, pointlocator, " & _
"pidgridcode from pipelineflow, pipelineproperties " & _
"where pipelineflow.lciid = pipelineproperties.lciid " & _
"and pipelineflow.audit_active = 1 " & _
"and pipelineproperties.audit_active =1 " &
_
"and pipelineflow.ldate " & dtInDate & _
"and pipelineproperties.stationname = '" & Stationname & "' "
For part 1 of your question, add an ORDER BY clause to your query. In this case: order by stationname
Part 2: Not sure why column names aren't being included in your query. You can explicitly name a column using something like the following (purely an example):
select mycolumn as "MyCustomizedColumnName" from mytable
That allows you to give columns names of your choosing. Having said that, you shouldn't be required to do so for every column, so I suspect something else is going on in your case.
I should probably add that a stored procedure (rather than dynamic SQL) will yield better runtime performance.
For ordering just put
Order By stationname
at the end of the Query.
You can iterate through the column names by using:
rst(1).Name
where rst is your recordset, and the number is the index of the column.
To sort your query results , use 'ORDER BY' at the end of the query. The last lines of your query would look like this
"and pipelineproperties.stationname = '" & Stationname & "' " & _
"ORDER BY pipelineproperties.stationname"
The column heading are returned in your query data, but not automatically written to the Excel worksheet. The code snippet below shows how to loop through the recordset's column headings and write them to the active cell's row.
'rst' refers to your recordset, update the name as required.
If Not rst.EOF Then
For x = 0 To rst.Fields.Count - 1
With ActiveCell.Offset(0, lcount)
.Value = rst.Fields(x).Name
End With
Next
End If
Make sure that you offset down from the active cell when writing the query results to the worksheet, otherwise your headings will be overwritten by the data.
Activecell.Offset(1,0).CopyFromRecordset rst