Why the Recordset from VBA just return one record? - vba

I have 3 tables, "persons", "per_resi" and "residence"
This three tables form a many to many relation.
Table "person" fields: id, name etc....
Table "residence" fields: id, Street etc.....
Table "per_resi" fields: person_id and residence_id (together principal index)
Well, the problem is when I design a query in the graphic Access tool it Works as it should be.
But if I do in VBA it only return 1 record.
Dim svivienda As String
Dim rvivienda As Recordset
svivienda = "SELECT tbl_persona.Id, tbl_vivienda.Calle, tbl_vivienda.Numero " _
& "FROM tbl_vivienda INNER JOIN (tbl_persona INNER JOIN tbl_perso_viv ON tbl_persona.Id = tbl_perso_viv.Id_persona) " _
& "ON tbl_vivienda.Id = tbl_perso_viv.Id_vivienda WHERE tbl_persona.Id = " & 168 & ";"
Set rvivienda = CurrentDb.OpenRecordset(svivienda, dbOpenDynaset)
I have tried LEFT JOIN and RIGHT JOIN but always the same just one record on the recordset.
Any ideas?
MS access 2013
Thanks in advance.

Thank guys,
This was a very novel question.
Here is the answer.
The RecordCount property does not report the amount of records you have.
The value of the RecordCount property equals the number of records
that have actually been accessed. For example, when you first create a
dynaset or snapshot, you have accessed (or visited) only one record.
If you check the RecordCount property immediately after creating the
dynaset or snapshot (assuming it has at least one record), the value
is 1. To visit all the records, use the MoveLast method immediately
after opening the Recordset, and then use MoveFirst to return to the
first record. This is not done automatically because it may be slow,
especially for large result sets.
Count the number of records in a DAO Recordset
Thanks!!!

Add following statement :
rvivienda.MoveNext
will return the next record of the recordset
or :
rvivienda.MoveLast
will return the last record of the recordset
You will see the result.
The goosie2018's answer is CORRECT. I just show you the simple way to understand.
SUMMARY
So, I think the recordset you get from the database will not show the result look like an Array or a List, but a cursor. And the default cursor points to the first row, so if you use :
rvivienda.RecordCount
you should receive the number of records you actually got.
Sorry for my English ! And thanks for reading.

Related

Calculating the number of like records in an unbound text box on a form. in MS Access 2016

I have an unbound text box [txt_AmendmentOF] on a form to count the total number of Amendments a specific record has in the database. So the user knows which amendment they are on. Just a simple you are on Amendment 3 out of 8. i have this calculation i am using in the Control Source field of the text box [txt_AmendmentOF]:
=IIf(IsNull([txt_Amendment]),0,Count([MIPR_Number]))
there is a Field on my table called [Amendment] its text box on the form is called [txt_Amendment]. I have the calculation return a zero in [txt_AmendmentOF] if [txt_Amendment] is null. I need it to count the record number [MIPR_Number] that are the same and return the total number of Amendments count in the [txt_AmendmentOF] text box. on my table i have private key field called [ID] it is an autonumber format. The problem with the code above is it is counting all the fields that have a [MIPR_Number] and returning the total row count of that. i am not an expert here so any help would be greatly appreciated.
Update to post..
I have also tried this and got an error in the text box
=IIf(IsNull([txt_Amendment]),0,Count([MIPR_Number]=[txt_MIPR_Number]))
Counting by a condition is one of the basic dataabase tasks. To get answers from a db, you have to query the database (and that is done by createing a query).
To count same[MIPR_Number]you have to group the data (a group contains same numbers), then count.
SELECT COUNT(id) as CountOfSameNr, [MIPR_Number] FROM Table GROUP BY [MIPR_Number]
Store this query as e.g CountMIPRNumber.
Now you have two options:
Use a Dlookup to get one value
=IIf(IsNull([txt_Amendment]),0,Dlookup("CountOfSameNr","CountMIPRNumber","[MIPR_Number] = " & [MIPR_Number]))
or add the query to form recordsource (join on [MIPR_Number], "SELECT * FROM TABLE" is forms query)
SELECT CountMIPRNumber.CountOfSameNr, TABLE.* FROM TABLE LEFT JOIN CountMIPRNumber ON TABLE.[MIPR_Number] = CountMIPRNumber.[MIPR_Number]
and reference the count field
=IIf(IsNull([txt_Amendment]),0,[CountOfSameNr])

DLookup: Criteria returning blank values

I am trying to create an expression in Access 2016 to return a value from another table when a key is matched from the current table. I am sure it is syntax related, but am at a loss....
I want to add the receipt date (in tbl_RECEIPTS) as a column in tbl_POs based on the key value from the two tables being equal. INNER JOIN doesn't work because if we have not received the item, the field returned by DLookup should be blank.
Here is what I have:
The key is a string value in both tables.
DLookUp('[DATERECEIVED]',"tbl_RECEIPTS"," '[tbl_POs].[KeyVal]' = '[tbl_RECEIPTS].[KeyVal]' ")
The query runs, but returns a blank value for every record.
Any help would be GREATLY appreciated!
It could be:
DLookUp("[DATERECEIVED]","tbl_RECEIPTS","[KeyVal] = '" & [tbl_POs].[KeyVal] & "'")
I found it!
Sorry to answer my own question but What worked was using a LEFT JOIN with the tables.
The result will return blanks in the new date field when no corresponding key value is found.

Access Check If DataSet contains string via vba Macro

Hello Stackoverflow community!
I am currently confronted with writing somthing, that automatically cleans up a database after certain requirements. Here is what I have to do:
If a cell in one table contains a certain substr (lets say "Mrs."), in another table a Togglebox is supposed to be checked (Yes if "Mrs." is contained and No if not)
I already worked out something that sets The Toggleboxes to -1 in that column, but I have to include a check, if it even has to be changed and in which row. For that I wanted to bring up an If-construction and a variable that would contain the ID of the first table's row to determine, which of the Rows in the second table have to be changed.
So the thought is like this:
If 1st_Table contains "Mrs." Then
CurrentDb.Execute "UPDATE 2nd_Table SET gender = -1 WHERE foo = 1st_Table.ID_Var"
1st_Table.ID_Var would contain the ID of the row of the first table
Now the more or less obvious question: How do I accomplish that?
This is bascally the first time working with VBA/Access AND SQL so I have no closer thoughts on how to do that.
Thanks in advance
Greetings
geisterfurz007
P.S. The variable names will be changed in the final version; they are just to visualize. Just saw that they were colored by SO.
Try this (SQL update query):
UPDATE 2nd_Table INNER JOIN 1st_Table ON 2nd_Table.ID = 1st_Table.ID
SET 2nd_Table.gender = -1
WHERE 1st_Table.PersonName LIKE '*Mrs.*'
ID -> reference between both tables
PersonName -> column in 1st table containing Mrs.

Calculation based on values in 2 different rows

I have a table in MS Access which has stock prices arranged like
Ticker1, 9:30:00, $49.01
Ticker1, 9:30:01, $49.08
Ticker2, 9:30:00, $102.02
Ticker2, 9:30:01, $102.15
and so on.
I need to do some calculation where I need to compare prices in 1 row, with the immediately previous price (and if the price movement is greater than X% in 1 second, I need to report the instance separately).
If I were doing this in Excel, it's a fairly simple formula. I have a few million rows of data, so that's not an option.
Any suggestions on how I could do it in MS Access?
I am open to any kind of solutions (with or without SQL or VBA).
Update:
I ended up trying to traverse my records by using ADODB.Recordset in nested loops. Code below. I though it was a good idea, and the logic worked for a small table (20k rows). But when I ran it on a larger table (3m rows), Access ballooned to 2GB limit without finishing the task (because of temporary tables, the size of the original table was more like ~300MB). Posting it here in case it helps someone with smaller data sets.
Do While Not rstTickers.EOF
myTicker = rstTickers!ticker
rstDates.MoveFirst
Do While Not rstDates.EOF
myDate = rstDates!Date_Only
strSql = "select * from Prices where ticker = """ & myTicker & """ and Date_Only = #" & myDate & "#" 'get all prices for a given ticker for a given date
rst.Open strSql, cn, adOpenKeyset, adLockOptimistic 'I needed to do this to open in editable mode
rst.MoveFirst
sPrice1 = rst!Open_Price
rst!Row_Num = i
rst.MoveNext
Do While Not rst.EOF
i = i + 1
rst!Row_Num = i
rst!Previous_Price = sPrice1
sPrice2 = rst!Open_Price
rst!Price_Move = Round(Abs((sPrice2 / sPrice1) - 1), 6)
sPrice1 = sPrice2
rst.MoveNext
Loop
i = i + 1
rst.Close
rstDates.MoveNext
Loop
rstTickers.MoveNext
Loop
If the data is always one second apart without any milliseconds, then you can join the table to itself on the Ticker ID and the time offsetting by one second.
Otherwise, if there is no sequence counter of some sort to join on, then you will need to create one. You can do this by doing a "ranking" query. There are multiple approaches to this. You can try each and see which one works the fastest in your situation.
One approach is to use a subquery that returns the number of rows are before the current row. Another approach is to join the table to itself on all the rows before it and do a group by and count. Both approaches produce the same results but depending on the nature of your data and how it's structured and what indexes you have, one approach will be faster than the other.
Once you have a "rank column", you do the procedure described in the first paragraph, but instead of joining on an offset of time, you join on an offset of rank.
I ended up moving my data to a SQL server (which had its own issues). I added a row number variable (row_num) like this
ALTER TABLE Prices ADD Row_Num INT NOT NULL IDENTITY (1,1)
It worked for me (I think) because my underlying data was in the order that I needed for it to be in. I've read enough comments that you shouldn't do it, because you don't know what order is the server storing the data in.
Anyway, after that it was a join on itself. Took me a while to figure out the syntax (I am new to SQL). Adding SQL here for reference (works on SQL server but not Access).
Update A Set Previous_Price = B.Open_Price
FROM Prices A INNER JOIN Prices B
ON A.Date_Only = B.Date_Only
WHERE ((A.Ticker=B.Ticker) AND (A.Row_Num=B.Row_Num+1));
BTW, I had to first add the column Date_Only like this (works on Access but not SQL server)
UPDATE Prices SET Prices.Date_Only = Format([Time_Date],"mm/dd/yyyy");
I think the solution for row numbers described by #Rabbit should work better (broadly speaking). I just haven't had the time to try it out. It took me a whole day to get this far.

compare all fields in access using vba/sql

I know I can compare values between two tables, but I have not needed to do it for more than 2 or 3 fields up to this point so comparing them each individually hasnt been an issue, I used code such as this:
DoCmd.RunSQL "INSERT INTO Issues
SELECT Eligibility.[Member Id]
, Eligibility.[Sex Code]
, Eligibility.State
FROM Eligibility LEFT JOIN Ref
ON Eligibility.[Sex Code] = Ref.[Sex Code]
WHERE (((Ref.[Sex Code]) Is Null));"
now however, i need to compare about 140 different fields. is there a better way to do this than writting 140 sql statements and running them all one by one?
i want it to find where fields dont contain the same info and then pull the entire row from both tables,or at the very least the value in the 5th column, member id, and then i can run another query to pull the entire row off of that value if need be (so i can look at both at the same time) and paste them into another table and highlight the cells where the mismatches occur.
both tables are in the same database
both tables have the same structure, but the second table might not have all of the values from the first, so i need to find a way to have it match the rows based on the member ID before it starts comparing the rows.
You can compare using DAO pretty easily. Using the .Fields() argument on a recordset you get all the different fields in the actual recordset.
This lets you do something like:
Sub exampleSQLComparison()
Dim rs1 As DAO.Recordset
Dim rs2 As DAO.Recordset
'.... set those recordsets via SQL statements
For Each f In rs1.Fields
If rs1.Fields(f) <> rs2.Fields(f) Then
Debug.Print "Mismatch found for " + f
End If
Next f
End Sub
If your queries are similar and the only thing you are changing is a single field (for example an ID) you should be able to modify the logic accordingly.