Microsoft Access Queries Too Many Fields - ms-access

I am dealing with approximately one dozen MS access tables that are all linked into a single database file.
Occasionally I would like to be able to get the union of these tables to generate a complete dataset. My attempts to do this so far result in a too many fields defined error.
Is there a way for me to do this using Microsoft access (I can use 2007 or 2010 versions)? If not, any other suggestions on how this could be achieved would be greatly appreciated.

According to the "QUERY" section of the "Access 2010 Specifications" topic in Access help, you are limited to 255 fields (columns) per recordset (query). If the "complete dataset" you want to produce will have more than 255 columns then you won't be able to do that in a single Access query.
One possibility might be to create several queries with no more than 255 columns each, export them to Excel, then paste them together side-by-side into a very wide Excel document. Excel_2010 worksheets can have up to 16,384 columns. It could be a bit tedious to do manually but there would be some opportunity to automate the process, at least in part. You'd also have to be careful that each "partial query" returned the same number of rows in the same order so things would "line up" when you pasted them together.

This answer is about a different occurrence of the "Too many fields defined" error from a query, and what I did to eliminate it.
I have a query that was giving me that error. Compacting the database didn't fix it. When I split the query into three queries with fewer fields in each, two of those smaller queries worked okay, but one still gave me the error. So it appeared that the problem had nothing to do with the number of fields, but with something about the coding of the query.
The query had two similar fields coded as subqueries:
(SELECT first([Date]) FROM [C:<path>\sources.accdb].[items - subjects] WHERE [Subject name] = SubjName and Assessment like "*Buy*") AS FirstBuyRecDate
and
(SELECT first([Date]) FROM [C:<path>\sources.accdb].[items - subjects] WHERE [Subject name] = SubjName and Assessment like "*Sell*") AS FirstSellRecDate
The error first arose when the second of those fields was added to the query. The query was able to work with either of those fields present, but not both. It was also able to work if the subquery in either of the fields was replaced with a random date constant, such as #2018 12 31#. So it appeared that the problem had something to do with those subqueries.
I was able to eliminate the error by changing those subqueries to function calls using a UDF I had previously developed for another purpose:
Public Function vFtnInQry(sField As String, sSQL As String) As Variant
' Return the value of the field with the name <sField> in the select query <sSQL>.
' The purpose of this is to allow inserting a variable value into the SQL of a query.
Dim oRecSet As DAO.Recordset, nCountRecords As Long, vRetVal As Variant
Set oRecSet = CurrentDb().OpenRecordset(sSQL)
nCountRecords = oRecSet.RecordCount
If (nCountRecords = 0) Then
vRetVal = Null
Else
vRetVal = oRecSet.Fields(sField).Value
End If
vFtnInQry = vRetVal
End Function
So the field definitions changed to:
vFtnInQry("BuyRecDate", "SELECT first([Date]) as BuyRecDate FROM [C:<path>\sources.accdb].[items - subjects] WHERE [Subject name] = """ & [SubjName] & """ and Assessment like ""*Buy*""")) AS FirstBuyRecDate
and
vFtnInQry("SellRecDate", "SELECT first([Date]) as SellRecDate FROM [C:<path>\sources.accdb].[items - subjects] WHERE [Subject name] = """ & [SubjName] & """ and Assessment like ""*Sell*""")) AS FirstSellRecDate
I don't know why this solved the problem. I'm posting it here in case someone else has a mysterious occurrence of "Too many fields defined" from a query that might be solved this way. On the other hand, if someone reading this sees a reason that those subqueries were causing that error, please post about that in a comment or another answer.

Related

Can I use DCount to populate a textbox with criteria from a different table?

I have been having much trouble with this problem. I have a table in Access called "Import" that I import records to. Each record has a facility name that corresponds to a "region" from a different table called "COID_Lookup". I'm trying to get a count of records in the "Import" table based on criteria from the "COID_Lookup" table. Is this possible? Also, I have a query that already does this perfectly but I understand a textbox value cannot be based on a query.
This is what I've tried =DCount("Facility","tblImport","tblCOID_Lookup.Region = 'Midwest'")
My output is #Error in the textbox that blinks as if it is caught in an endless loop.
The query I have, Midwest_Count, works as expected, but I don't know how to put that in the expression. I have tried to look it up but the answers don't make sense to me. I'm sorry.
The solution I used is a DLookup of the query I had that worked.
=DLookUp("CountOfFacility","qryMidwest_Count")
This is the query.
SELECT Count([tblImport].Facility) AS CountOfFacility FROM tblCOID_Lookup INNER JOIN tblImport ON tblCOID_Lookup.[Facility] = tblImport.Facility WHERE (((tblCOID_Lookup.Region)="Midwest"));
Yes, you can do that, as DCount will accept an SQL criteria value:
=DCount("*", "tblImport", "[Facility] = (Select [Facility Name] From tblCOID_Lookup Where [Region] = 'Midwest')")

Access - Left Join returns #Error instead of Null

I've asked a similar question already, but I've now simplified the tables/queries enough to put up an example database with (hopefully) descriptive naming:
https://docs.google.com/file/d/0B2PZcGkhNyd4THpWa01fTjVvSWM/edit?usp=sharing
There is one query, ChainsCasesPerMonthPerStorePreviousMonthRange, which works fine. It takes data from two tables and the QueryDatesPrevious query, to return data for the previous period to the one specified in the QueryDates table. Everything seems okay up to this stage.
But when I run the query LeftJoinReturnsError, the three extra chains in the Chains table return #Error instead of returning the expected Null.
If I change QueryDatesPrevious from a query to a table everything works fine, so this seems to be where the problem lies, but I can't seem to solve it, even using an Iif(IsNull, Null, 0) condition.
An extra 50 rep points to the person who solves it, as long as I can work out how to transfer them across. :)
(previous question if you're interested: Access 2007 - Left Join to a query returns #Error instead of Null)
-- EDIT UPDATE --
Output would look something like this, although I don't remember the exact data I put in the test database:
Chain CasesPerMonthPerStore
AgriStore 2.33
Agricultural Export
2B Pencils 3.6
Bob's Markets
So basically, any chain in the Chain table that isn't in the other tables should return Null as part of the left join.
This is rather ugly too, but it seems to work:
Run the following query to create a table named [tblChainsCasesPerMonthPerStorePreviousMonthRange]:
SELECT ChainsCasesPerMonthPerStorePreviousMonthRange.*
INTO tblChainsCasesPerMonthPerStorePreviousMonthRange
FROM ChainsCasesPerMonthPerStorePreviousMonthRange;
Create a query named [updChainsCasesPerMonthPerStorePreviousMonthRange] as an Update query that saves the results of [ChainsCasesPerMonthPerStorePreviousMonthRange] into [tblChainsCasesPerMonthPerStorePreviousMonthRange]:
INSERT INTO tblChainsCasesPerMonthPerStorePreviousMonthRange
SELECT ChainsCasesPerMonthPerStorePreviousMonthRange.*
FROM ChainsCasesPerMonthPerStorePreviousMonthRange;
Paste the following Function into a standard VBA Module
Public Function RemakeTable() As Variant
Dim qdf As DAO.QueryDef
Debug.Print "Executing RemakeTable()..."
CurrentDb.Execute "DELETE FROM tblChainsCasesPerMonthPerStorePreviousMonthRange", dbFailOnError
Set qdf = CurrentDb.QueryDefs("updChainsCasesPerMonthPerStorePreviousMonthRange")
qdf.Execute
Set qdf = Nothing
RemakeTable = Null
End Function
Update your [LeftJoinReturnsError] query to
SELECT
Chains.Chain,
tblChainsCasesPerMonthPerStorePreviousMonthRange.CasesPerMonthPerStore,
RemakeTable() AS Junk
FROM
Chains
LEFT JOIN
tblChainsCasesPerMonthPerStorePreviousMonthRange
ON Chains.Chain=tblChainsCasesPerMonthPerStorePreviousMonthRange.Chain;
The final query has an extra column named [Junk], but at least we get the desired result.
Note: I put the Debug.Print in the VBA Function to verify that it only gets called once, not once for each row in the query.
Great post on the bug. I hadn't seen that, but it's quite obvious that's exactly what's happening. The only way I can see to deal with it since Access doesn't support lateral joins or SQL Server's APPLY clause, is to elevate the expression to the select clause in the top level query. The following gives you the output you want:
SELECT Chains.Chain, (SELECT ChainsCasesPerMonthPerStorePreviousMonthRange.CasesShipped/(DateDiff("m",ChainsCasesPerMonthPerStorePreviousMonthRange.StartDatePrevious,ChainsCasesPerMonthPerStorePreviousMonthRange.EndDatePrevious)+1)/ChainsCasesPerMonthPerStorePreviousMonthRange.NumberOfStores AS Expr1 from ChainsCasesPerMonthPerStorePreviousMonthRange WHERE ChainsCasesPerMonthPerStorePreviousMonthRange.Chain = Chains.Chain) as Expr2
FROM Chains;
It's pretty ugly, but it works. Of course in SQL Server or another DB, you wouldn't need lateral joins because the process outer joins with expressions correctly.
Okay, so I set up another query that just returns the chains that should return a Null value for CasesPerMonthPerStore, but are actually returning #Error in my test database:
SELECT Chains.Chain
FROM Chains LEFT JOIN ChainsNumStoresPreviousMonthRange ON Chains.Chain = ChainsNumStoresPreviousMonthRange.Chain
WHERE ChainsNumStoresPreviousMonthRange.NumberOfStores Is Null;
So in my written example in the question above this query would return:
Chain
Agricultural Export
Bob's Markets
I then UNION these chains, along with a Null field, to the query that returns all of the chains that do return a value for CasesPerMonthPerStore:
SELECT *
FROM (SELECT ChainsCasesPerMonthPerStorePreviousMonthRange.Chain, ChainsCasesPerMonthPerStorePreviousMonthRange.CasesPerMonthPerStore
FROM ChainsCasesPerMonthPerStorePreviousMonthRange
UNION ALL
SELECT ChainsNotInPreviousPeriod.Chain, NULL
FROM ChainsNotInPreviousPeriod) AS UnionQuery
ORDER BY Chain;
So the secret seems to be to separate the calculated field away from the left join. It's the first time I've come across this error, and I don't know whether this approach would work in every situation, but it worked for me. :)
Thanks for your time Brian & Gord,

Access / DCount gives a TExt field and not INT field?

In Access 2010, I have two tables 'Contact' and 'PhoneCalls'.
I created this Query for 'Contact' as I want to see how many times I called a contact.
Query:
SELECT Contact.*, DCount("[ID]","ColdCall"," [ColdCall]![ContactID] = " & [Contact.ID]) AS Call
FROM Contact
I have build this query using the following expression:
Call: DCount("[ID]","ColdCall"," [ColdCall]![ContactID] = " & [Contact.ID])
It works fine except that it creates a TEXT field instead of a NUMBER field. For instance, I need to sort this query out, but I can only sort it "A to Z" and not "smallest to largest" as it should be.
Do you have any idea on how I can solve that?
You could use CInt() to force the call count to be an integer:
SELECT Contact.*, CInt(DCount("[ID]","ColdCall"," [ColdCall]![ContactID] = " & [Contact.ID])) AS Call
FROM Contact;
Note also that using DCount() in this way is rather inefficient. If that approach works to your satisfaction then continue to use it for now, but don't be surprised if it starts to bog down as the tables grow.

Returning specific field from a matching record

I'm still a newbie at Access 2007, but I feel I am missing a understanding of a concept, when it comes to using user input from an unbound text box.
I'm trying to have the user input the record number (i.e. A12) and return another field in the matching record (such as the record status like "Opened")
I'm fiddling with DLookup to see if it will work through that method but no luck yet.
I may look into SELECT - SQL, but I haven't used that function yet and not sure if that will give me the result I'm looking for.
If this is something elementary to access programming (or databases in general), please let me know where I can read up on this.
I am currently using the MSDN website, but examples go much further to play with.
Edit:
My DLookup so far, which happens after update from user on Text12
Me.Text14.Value = DLookup("[RecordStatus]", "Orders", Text12.Value)
Thanks
Look closer at the third option (Criteria) in your DLookup() expression. You gave it only Text12.Value, which I assume is a string value like "A12".
The Criteria parameter should be like a WHERE clause in a query, without the word WHERE. IOW, some field's value = "A12". If that field is named "record_id", try this:
DLookup("RecordStatus", "Orders", "record_id = '" & Me.Text12 & "'")

ms access complicated query. querying last two entries by date for each ID. very slow

I have two tables. Widgets, which has information about each widget (Color, size, etc); each widget has a unique ID, WidgetID.
The other table is Tests, and it contains information about multiple tests that were run on each widget. This table, therefore, has multiple rows for each WidgetID. It contains information that we can call (WidgetID, Date, Param1, Param2, etc); test information.
I have written a query that finds, for each WidgetID, the most recent two tests by date. The SQL looks like this:
SELECT Widgets.WidgetID, Widgets.Color, Widgets.Size, T.Date, T.Param1, T.Param2,*
FROM Tests AS T INNER JOIN Widgets ON T.WidgetID=Widgets.WidgetID
WHERE (((Select COUNT(*) FROM Tests
WHERE WidgetID = T.WidgetID AND Date > T.Date)) < 2 );
This works very well. However, it gives me too many widgets. I have created a query that filters the widgets called WidgetFilter. It basically just chooses the ones i want based on whatever i choose. The idea was that I would run the same query replacing "Widgets" in the code above with "WidgetFilter." However, when I do this it takes forever. In fact, it just freezes. I left it for an hour and a half and it just sat there and i had to alt ctl delete. My only thought is that it is querying the WidgetFilter query for every row of Tests (and thats a lot of rows). I also tried applying the filter criteria within the original query. I get the same result.
Is there a better way to do this? Either a single query that does it all and possibly doesnt even look like this or what i was thinking is that there should be a way to run the WidgetFilter query once and make that data look to access like a table (isnt there such a thing as a temp table). That way it doesnt run WidgetFilter for every item in Tests.
EDIT:
WidgetFilter is actually pretty complex. I have created these GUI pick tables where the user sees two columns. The choices on the left and the list he/she is creating on the right and in the middle there is an add button and a delete button. They then call the report which executes WidgetFilter, yadda yadda yadda. Anyway, when the user adds an item, it adds that item to a table. So for the Widget category, Color, there will be a table called ColorList. The user constructs this list through the gui. There are three of these guis (Color, Size, Type). For each of them there is a table and there is then a Global boolean (eg, ColorFlag) that tells which filter to use (Color, Size, or Type).
So, in the WidgetFilter query, the criteria box under Color will have this:
In(Select Color From ColorList)
and there is an expression column Expr1: getColorFlag() which is a module that returns the value of the Global variable ColorFlag. and it is true at the same time the color table is applied. So, when all is said and done there are three rows of criteria. The code looks like this:
Select Widgets.WidgetID, Widgets.Color, Widgets.Size, Widgets.Type
From Widgets
WHERE (getColorFlag() = True AND (Widgets.Color) In(Select Color FROM ColorList))
OR (getSizeFlag() = True AND (Widgets.Size) In(Select Size FROM SizeList))
OR (getTypeFlag() = True AND (Widgets.Type) In(Select Type FROM TypeList))
One thing you may not be aware of. I believe that most versions of Access (don't know about 2007) will go off to loopy land if you have a sub-select that returns a NULL value for any row. So, if there is a NULL Color, Size, or Type in any of those tables that would cause the symptoms you're seeing.
Ok. Here's what I ended up doing. I created a temp table through VBA code like this:
Function createWidgetFilterTemp()
Dim mySQL
Dim deleteSQL
deleteSQL = "DELETE * FROM TempWidgetFilter"
mySQL = "SELECT * INTO TempWidgetFilter FROM WidgetFilter"
DoCmd.SetWarnings False
DoCmd.RunSQL deleteSQL
DoCmd.RunSQL mySQL
DoCmd.SetWarnings True
End Function
I Inner Joined TempWidgetFilter and Tests in a query called WidgetCombo. This gave me access to all the Test information and all the Widgets information for only the WidgetIDs that i was interested in. I tried to do the same query with the Select Count(*) statement, but i got the same problem with Access freezing up. So, I then created another temp table through VBA using code like this:
Function createWidgetTemp()
Dim mySQL
Dim deleteSQL
deleteSQL = "DELETE * FROM TempWidgetCombo"
mySQL = "SELECT * INTO TempWidgetCombo FROM WidgetCombo"
DoCmd.SetWarnings False
DoCmd.RunSQL deleteSQL
DoCmd.RunSQL mySQL
DoCmd.SetWarnings True
End Function
I ran both of these functions whenever I called for the querys from the form. This worked!! It worked fairly quickly, actually. I think it would have worked without the first temp table, but having that as a temp table rather than just a query made another part of my app run faster so i left it. By the way, I had to run it once with the delete line commented off so that it would create the table. I think i might have been able to just create the table by hand, but this way it got all the fields in there in the correct way. Thanks for the help, I hope this helps someone else who comes by in the future looking for temp table help.
Simple, really.
SELECT TOP 2 Widgets.WidgetID, Widgets.Color, Widgets.Size, T.Date, T.Param1, T.Param2,*
FROM Tests AS T INNER JOIN Widgets ON T.WidgetID=Widgets.WidgetID
ORDER BY T.Date DESC