MS Access: divide result set into multiple pieces by text value or number of rows - sql

I have a query against an Item table. This is all the items our library has, e.g., books, DVDs,CDs, etc.
I have to send a tab-delimited file that contains data on all these items.
There are over 100,000 items.
I'm stuck using MS Access.
Access can pull all the data, but it cannot send the result set via email because it is too big (over 65,535 rows; I am aware that later versions of Excel past 2007 can hold more rows but that does not help me).
All the columns are text data. So normal relational operators won't work (I tried).
I need to split the result set into two or three result sets in order to get it from Access to Excel. The need for Excel is that this is how the vendor expects it, and it needs to be tweaked some before shipping.
How can I divide it?
I have thought of at least two ways
If I can count rows, I can tell Access to use the first 60,0000 rows it gets. How do I tell it do that and then fetch only the second set of all the rows past 60,000. I have not figured out how to do this.
Divide based upon a field. The only field that is unique is the barcode, e.g., "30001001672906" Usually, the barcode is 14 numbers in length. I have experimented with using StrComp in a where clause, but I have a problem:
The barcodes are not in sorted order before they are fetched. "Order by" works on the result set, not how the data is processed before it is selected.
I am at a loss as to how to accomplish my big goal. That's the one that matters, not the particular way to fix my SQL to get it. I've looked at some pages, such as those below but not found a solution.
https://support.office.com/en-us/article/Table-of-operators-e1bc04d5-8b76-429f-a252-e9223117d6bd#__toc272228349
MS ACCESS count/sum number of rows, with no duplicates
http://www.techonthenet.com/access/functions/string/strcomp.php

I don't understand the problem with 2.
SELECT barcode FROM items ORDER BY barcode
Open a Recordset on that, move to record 60000, get the barcode
rst.Move 60000
strBarcode = rst!barcode
See https://msdn.microsoft.com/en-us/library/bb243789%28v=office.12%29.aspx
Then build your queries dynamically.
myQuerydef.SQL = "SELECT * FROM items WHERE barcode <= '" & strBarcode & "'"
Export the query e.g. with DoCmd.TransferSpreadsheet
myQuerydef.SQL = "SELECT * FROM items WHERE barcode > '" & strBarcode & "'"
Export to second file.
If you need more than two files, use an array instead of strBarcode and do
myQuerydef.SQL = "SELECT * FROM items WHERE barcode > '" & Barcode(i) & _
"' AND barcode <= '" & Barcode(i+1) & "'"

Related

Why the Recordset from VBA just return one record?

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.

Updating filling in blanks on SQL table based on csv

I am working on a small project at my office to do some clean up on our customers table stored in SQL Server and a similar one stored in PostgreSQL. Basically we found many customers have one or several columns that have 0 or are blank and need to be filled in. Our plan is to first gather all of the data for the 0 or blank columns and fill in the csv, and then somehow script it to fill in the blank columns for each customer.
Below is an example of what the current table looks like with 0s and blank columns. It's random as to which column or columns need to be filled in for a given customer (the one thing we always have is the customer's username).
username emp_num title email phone
-------------------------------------------------------------------
jsmith 0 Manager jsmith#somewhere.com
kjones 112222 Clerk 111-222-3333
wgarcia 0 wgarcis#domain.com 444-555-6666
We would be filling in anything with "0" with a 6 digit number and any blanks would have values filled in on the csv.
Question is, after I have a completed csv with all customer info, how might I go about:
loading the csv into SQL; and
scripting this to compare the csv file against the existing customer table and fill in only what's missing? (i.e. 0s and blanks).
Can anyone share example SQL queries to get me started? (How might it need to be approached differently for PostgreSQL?)
TIA,
Chris
Update off a join to the correct customer table like this:
update a
set a.emp_num=b.emp_num
from currenttable a join customer b on a.username=b.username
where a.emp_num in (0,'')
Presumably this is a one time task. You can do this very easily with some simple string building using Excel or another spreadsheet application. It won't be reusable, but it's often the quickest solution.
That said it isn't going to work if you have a very large number of customers, but it'll do the trick for several thousand.
Excel Formula
="UPDATE YourTable SET emp_num = " & B2 & ", title = '" & C2 & "', email = '" & D2 & "', phone = '" & E2 & "' WHERE username = '" & A2 & "'"
Simply copy the formula to all the rows in your csv, and execute the generated queries.

How do I get three columns to concatenate into one combo-box in Access 2010

I have a combo-box in an Access 2010 form that I want to show the concatenation of three fields in three separate columns as a result. Currently, I only get the first column to show upon selection even though all three show in the dropdown. The previous questions I have looked at seem to deal with platforms I'm not using.
In a qry, I have the following simple SQL statement that combines all three into a Desc column.
SELECT tblReLetArea.CWHContractNo, tblReLetArea.ReLetAreaLot, tblReLetArea.ReLetAreaName, tblReLetArea.[CWHContractNo] & ": " & [ReLetAreaLot] & " - " & [ReLetAreaName] AS [Desc]
FROM tblReLetArea;
I have attempted variations but nothing changes and I don't get any error messages.
You need to set two things:
The amount of columns in the combobox (combobox.ColumnCount) must be set to 4
The column widths of the combobox (combobox.ColumnWidths) must be set to 0;0;0 to hide the first 3 columns
Note that you could indeed remove the first 3 columns from your query altogether, or reorder the columns. That would influence the availability of the columns in VBA.

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.

Why does the count function in SQL seem to be doing more than counting the column I ask it to?

I have an INSERT query that is pulling data from two tables and inserting that data into a third table. Everything appears to be working fine except that the COUNT part of the query isn't returning the results I would expect.
The first set of tables this query runs is MIUsInGrid1000 (number of rows = 1) and Results1000 (number of rows = 24). The number that is returned from the Count part of the query is 24 instead of being 1 like I would have expected.
The next set of tables is MIUsInGrid1000 (number of rows = 3) and Results1000 (number of rows = 30). The number that is returned from the Count part of the query is 90 instead of being 3 like I would have expected.
It appears that the product of the two counts is what is being returned to me and I can't figure out why that is. If I take out the references to the Results tables then the query works the way I would expect. I think that I am misunderstanding how at least some part of this works. Can someone explain why this is not working as I expected it to?
strQuery1 = "Insert Into MIUsInGridAvgs (NumberofMIUs, ProjRSSI, RealRSSI, CenterLat, CenterLong) " & _
"Select Count(MIUsInGrid" & i & ".MIUID), Avg(MIUsInGrid" & i & ".ProjRSSI), Avg(MIUsInGrid" & i & ".RealRSSI), Avg(Results" & i & ".Latitude), Avg(Results" & i & ".Longitude) " & _
"From MIUsInGrid" & i & ", Results" & i & " "
It seems logical to me that if you are joining two tables, one with 1 row and the other with 24 rows that there, is the possibility, of having a result set of 24 rows.
I notice you have not included a WHERE clause in your SQL (perhaps for brevity), but if you don't have that you are doing a CROSS JOIN (or cartesian join) between the tables and this will provide unexpected results.
The COUNT function will count all rows in the database, to determine how many "distinct" ID's there are, you can use the answer provided by Tomalak
This should solve your immediate problem
Count(DISTINCT MIUsInGrid" & i & ".MIUID)
The naked COUNT function counts the non-NULL values, not the distinct values, unless you tell it to switch behavior by using DISTINCT.
When two tables are joined like you do it (you build a cartesian product), then the number of resulting rows is the number of rows in the one times the number of rows in the other table.
This leads me to the suspicion that you are missing a join condition.
Apart from that i find it bewildering that you have a number of obviously identical tables that are indexed by name. This most certainly is a substantial design flaw in the database.
The way I usually figure these things out is to not use any aggregates first to see what my result sets will be. Then, I start adding in the aggregate functions.