Query with multiple Left Joins to ODBC tables fails - sql

I posted this originally without all the ODBC information. After further investigation the problem appears to the ODBC related. Given the change, I wanted to report and see if an ODBC guru might be "listening".
I have the following queries in Access...
Query #1
SELECT aa.DocNum, b.QualityClass
FROM dbo_TransferHistory AS aa LEFT JOIN PCQualityClass AS bb ON aa.DocNum = bb.DocumentNum
WHERE (((aa.DocNum)=[Enter Doc Num]));
Which I want to expand to...
Query #2
SELECT aa.DocNum, bb.QualityClass, cc.BldgCond
FROM (dbo_TransferHistory AS aa LEFT JOIN PCQualityClass AS bb ON aa.DocNum = bb.DocumentNum)
LEFT JOIN PCBldgCond AS cc ON aa.DocNum = cc.DocumentNum
WHERE (((aa.DocNum)=[Enter Doc Num]));
dbo_TransferHistory is an table I access through an ODBC connector.
PCQualityClass and PCBldgCond are two queries that are based off another ODBC table. The SQL for those queries is ...
Query for PCQualityClass
SELECT aa.DocumentNum, aa.Value AS QualityClass, aa.ResourceID, aa.BldgSeqNum
FROM dbo_PCBldgDetail AS aa
WHERE (((aa.DocumentNum)=[Enter Doc Num]) AND ((aa.ResourceID)="QualityClass") AND ((aa.BldgSeqNum)=[Enter Bldg Num]));
Query for PCBldgCond
SELECT aa.DocumentNum, aa.Value AS BldgCond, aa.BldgSeqNum, aa.ResourceID
FROM dbo_PCBldgDetail
WHERE (((aa.DocumentNum)=[Enter Doc Num]) AND ((aa.BldgSeqNum)=[Enter BldgNum]) AND ((aa.ResourceID)="Condition"));
DocNum and DocumentNum are the same type ("Short Text" and a length of 12) and while I would like to make the names the same, I cannot.
When the query is run, an Inputbox pops up and [Enter Doc Num] is replaced with the Document Number I want the data for.
The queries were created in Access using the Create Query tool. Access is willing to create the query and the SQL looks good.
The problem is that while Query #1 will work, Query #2 causes the error "Invalid Operation". As a note, if I take the first join out of query #2 and run the remainder as a single join, the query works.
Changing to inner joins will allow Query #2 to function but will cause issues as there are times that one or both of the two sub queries do not have data but I still need the data from the primary table.
Changing from ODBC tables to local tables solves the problem but is not a viable solution as the ODBC tables cannot be local.
Does anyone have any insight into the inter-workings of Access and ODBC? I have a hard time believing that I am the first person who has tried to build an Access/Odbc query with more than one join. Yet I have not been able to Google a solution to this problem.

Related

Visual Basic 6 and dbf: issues with 'join' and 'where'

I need to modify an old vb6 application that needs to import some data from a dBase IV database.
In the past the selection query involved a single table (dbf file) and used to work perfectly.
Now i need to edit this query to introduce a join on a second table, using multiple fields.
This is a simplified version of my code:
Dim cnn As New Connection
Dim rs As New Recordset
Dim sql As String
cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Extended properties=dBase IV;Data source=d:\100\db;"
sql = "..." 'see below!
rs.CursorLocation = adUseClient
rs.Open sql, cnn, adOpenDynamic, adLockOptimistic
debug.print rs.RecordCount
rs.Close
cnn.Close
These two tables have a typical master-detail structure; I checked the db documentation and inspected TABFAT01 and TABFAT02, so I can assume that:
Join between these tables is [TABFAT01] 1 <-> n [TABFAT02], and is done on
TIPDOC (text), ANNDOC (text) and NUMDOC (numeric) fields.
Each row in TABFAT01 has at least 1 joined row in TABFAT02.
Each row in TABFAT02 has 1 joined row in TABFAT02.
TABFAT01 has 63 records.
TABFAT02 has 907 records.
First issue
My first query is:
select t.TIPDOC, t.NUMDOC, t.ANNDOC, t.DATDOC, t.LIBER03, c.LIBER04
from TABFAT01 t inner join
TABFAT02 c on t.TIPDOC = c.TIPDOC and t.ANNDOC = c.ANNDOC and t.NUMDOC = c.NUMDOC
This query returns 0 records.
If I change conditions order this way:
select t.TIPDOC, t.NUMDOC, t.ANNDOC, t.DATDOC, t.LIBER03, c.LIBER04
from TABFAT01 t inner join
TABFAT02 c on t.ANNDOC = c.ANNDOC and t.NUMDOC = c.NUMDOC and t.TIPDOC = c.TIPDOC
the query returns 907 records.
I don't understand how and why conditions order has impact on query results.
Second issue
If I add a where clause:
select t.TIPDOC, t.NUMDOC, t.ANNDOC, t.DATDOC, t.LIBER03, c.LIBER04
from TABFAT01 t inner join
TABFAT02 c on t.ANNDOC = c.ANNDOC and t.NUMDOC = c.NUMDOC and t.TIPDOC = c.TIPDOC
where c.LIBER04 = 'a'
the query returns 0 records.
However, if I run this query:
select * from TABFAT02 c where LIBER04 = 'a'
it returns 1 record, with TIPDOC = 'F2', ANNDOC = '2018', NUMDOC = 1854.
A subsequent query:
select * from TABFAT01 t where t.TIPDOC = 'F2' and t.ANNDOC = '2018' and t.NUMDOC = 1854
returns 1 record, as expected.
This happens for every field I tried to put in where clause with joined tables, except TIPDOC.
If I filter by TIPDOC, results are correct.
Third issue
The first time I run my code after opening vb6 IDE it gives the following error:
Run-time error '-2147467259 (80004005)': Selected Collating sequence Not Supported by the operating system.
(I actually use the Italian version of vb6, and the original error message says "Sequenza di ordinamento selezionata non supportata dal sistema operativo.".
I guess that the message I written above is the right match for the English version.)
This error is not displayed on subsequent runs, until I close and reopen vb6.
I agree with thx1138v2 about not specifically using the Jet OleDB driver, but one more specific to the source. You mention dBASE IV. Is this accurate or is it really with Visual FoxPro. You could confirm if the table has indexes and note (memo) fields the file names would be suffixed as
YourTable.dbf (actual table)
YourTable.cdx (compound index file)
YourTable.fpt (notes/memo file content is table has such columns).
Having confirmed, and if it IS Visual Foxpro, I would get the Microsoft driver directly from Microsoft
If the data table is being updated from a source outside VFP, then it is possible that the indexes may be out of sync as the other drivers won't necessarily open the index file (cdx) correctly to keep the new records in synch. So when trying to do the join based on one series of join clauses it does use the non-synched index. But changing the order forces to default to the natural order, thus seeing all possible records to resolve.
See and hopefully this makes sense and helps to tune-in on the missing link in your querying issue.
First clear up your error message. "Selected Collating sequence Not Supported by the operating system." probably means you didn't specify a collating sequence or the Jet.OLEDB driver doesn't support whatever collating sequence you specified.
I never got the Jet.OLEDB drivers to work with my application. My guess is because the files I was dealing with were created by FoxPro. So I used the Visual Fox Pro ODBC drivers. Here's an example connection.
"DSN=BCLVariance;UID=;SourceDB=C:\AMSI\BCLTemp;SourceType=DBF;Exclusive=Yes;BackgroundFetch=No;Collate=Machine;Null=Yes;Deleted=Yes;"
You will see that it allows you to control various parameters that you aren't controlling in your Jet.OLEDB connection string. The ODBC data source is setup under System Data Sources tab in ODBC Data Source Administrator.
I never understood exactly why but the sequence you state the table names in a SQL query does make a difference. It has to do with how the internal query interpreter handles them. You need to specify the detail table first and the master is joined to the detail. Like this:
select t.TIPDOC, t.NUMDOC, t.ANNDOC, t.DATDOC, t.LIBER03, c.LIBER04
from TABFAT02 c inner join
TABFAT01 t on t.TIPDOC = c.TIPDOC and t.ANNDOC = c.ANNDOC and t.NUMDOC = c.NUMDOC
That may also clear up your other problems. Give it a try.
BTW, you'll also need to change your initial code to:
if Not rs.BOF then
rs.MoveLast
debug.print "rs.RecordCount=";rs.RecordCount
else
debug.print "rs.BOF = True"
end if

Using Microsoft Query in Excel to Add Date Parameters to SQL Query

I often use the function (now legacy) in Excel to get data from SQL Server where I paste an actual SQL statement into the Excel sheet and it works fine. I have been researching how to do this with queries I have that have date parameters that need to be changed each time a report is ran and at first it seemed like using Microsoft Query in Excel would be the best option. This would use the '?' instead of the dates themselves and allow for adding parameters. Whenever I try to do this with the below query I get the error "Parameters are not allowed in queries that can't be displayed graphically." I honestly have no idea what that means but would value any input. My Query is below. Thanks
SELECT E.TEAM_MEMBER_NAME AS 'PURCHASER',
M.DEPARTMENT,
M.BUSINESS_SEGMENT_CODE,
KB.BUSINESS_SEGMENT_DESC,
KG.GENDER_DESC,
MR.PLANT_CODE [PLANT],
MR.STOCK_CATEGORY,
M.MATERIAL,
M.[DESCRIPTION],
M.COLOR_1,
M.COLOR_2,
MR.SIZE_LITERAL,
MR.QUANTITY,
M.STANDARD_COST,
M.DEALER_PRICE,
M.CURRENT_SEASON,
MR.STOCK_NUMBER AS 'AFS PO #',
H.PO_CREATED_BY,
H.PO_TYPE,
MR.MRP_INDICATOR,
MR.STOCK_TYPE,
H.PO_ISSUE_DATE
FROM PDX_SAP_USER..VW_MRP_ALLOCATION MR
JOIN PDX_SAP_USER..VW_MM_MATERIAL M ON MR.MATERIAL = M.MATERIAL
JOIN PDX_SAP_USER..VW_KD_BUSINESS_SEGMENT KB ON M.BUSINESS_SEGMENT_CODE = KB.BUSINESS_SEGMENT_CODE
JOIN PDX_SAP_USER..VW_KD_GENDER KG ON M.GENDER_CODE = KG.GENDER_CODE
JOIN PDX_SAP_USER..VW_PO_HEADER H ON MR.STOCK_NUMBER = H.PO_NUMBER
JOIN ADI_USER_MAINTAINED..SCM_PO_EMPLOYEE_NAME E ON MR.STOCK_NUMBER = E.PO_NUMBER
WHERE M.BUSINESS_SEGMENT_CODE NOT IN ('420','421','422','424')
AND MR.STOCK_CATEGORY NOT LIKE 'A60383%'
AND MR.STOCK_CATEGORY NOT IN ('A60382001','A60380070')
AND M.MATERIAL NOT IN ('AY1480','CD4683')
AND H.PO_TYPE NOT IN ('02','06','10','UB','DB')
AND MR.MRP_INDICATOR IN ('A','N')
AND MR.STOCK_TYPE = 'B'
AND MR.QUANTITY >= 50
AND H.PO_ISSUE_DATE BETWEEN '09/26/2018' AND '10/10/2018'
ORDER BY MR.QUANTITY DESC
I got it to work...a bit of a work around. I had my DBA create a view on our server and selected all from that view. I then used MS Query to bring in the data and replaced the dates with ?. From there in the data source within Excel you can assign those question marks to cells in which you enter your dates. Works like a charm. And not taking credit - all credit goes to:
https://www.youtube.com/watch?v=xPalEw4xw1w
Short answer is that I've researched it at the time as well, trying my best to pass parameters (let's say, 'Sheet1!A1' cell) and couldn't. There is no real way to do it UNLESS you're using the Power Query as well as using an SQL stored procedure.
Do you think you can ask your DBA (or whomever is responsible for the database) to create a stored procedure for you in which you'd pass the date parameters? That's basically your only way to create a parameterised query.

Long Text Field over 255 Characters gets truncated

Not sure why my field in my query is getting truncated upon the return of the result. The value is being stored in the field, but gets truncated by access to help with "performance". I have reviewed multiple forums and SO posts to no avail.
Problems listed at link do not apply, Aggregation, Uniqueness, Union, Format Property, Row Source
What is wrong with my query? Instructions field in the Customer table is the one that is getting truncated.
Here is the raw query generated by access:
SELECT Task.ID, Task.TaskID, Task.TaskName, Task.TypeID, TaskType.TaskTypeName, Task.CustomerID, Customer.CustomerName, Customer.OnHold, Customer.Blacklisted, Customer.CustomerEngagementRecieved, Customer.AutoEmail, Customer.SpecialInstructions, Customer.Instructions, Task.QuoteRequired, Task.PriorityID, Priority.Priority, Task.Min, Task.Max, Task.Projected, Task.DeadlineDate, Task.ResourceID, Resource.ResourceName, Resource.Email, Resource.Extension, Task.Description, Task.StatusID, Status.Status, Task.DeveloperLog, Task.TaskPOCID, POC.Phone, POC.Email, Task.OtherPOC, Task.OtherPOCPhone, Task.OtherPOCEmail, Task.FolderPath, Task.StopBilling, Task.Premium, Task.EntryDate, Task.CompleteDate, Task.AssignedBy, Task.SettingsID, Settings.AutoEmail
FROM TaskType
INNER JOIN (Status
INNER JOIN (Settings
INNER JOIN (Resource
INNER JOIN (Priority
INNER JOIN (Customer
INNER JOIN (Task
INNER JOIN POC ON Task.TaskPOCID = POC.POCID)
ON Customer.CustID = Task.CustomerID)
ON Priority.PriorityID = Task.PriorityID)
ON Resource.ResourceID = Task.ResourceID)
ON Settings.SettingsID = Task.SettingsID)
ON Status.StatusID = Task.StatusID)
ON TaskType.TTID = Task.TypeID;
`
Have a close read of this - http://allenbrowne.com/ser-63.html something in your set up will causing the truncation.
If it's when you cut and paste the query results that can also be mis-leading. When you say a Long Text are these linked tables?
I'd also rename your Min and Max fields as they are reserved words and may cause access to think you are aggregating your data.
So from the sounds of it, Access just sometimes will ALWAYS truncate the field no matter what the settings. There is a way to force access to show the entire field though, by using the DLOOKUP() function instead of using a Control Source.
Here is the Answer to my current Issue for reference,
=DLOOKUP("Instructions", "Customer", "CustID=" & [CustomerID])

Are multiple JOINs unavailable when using ADODB to query an Excel file in a VBA procedure?

I have 3 sheets with data formatted as tables. The sheets names are "Riesgos", "Eventos" and "EventosRiesgos".
EventosRiesgo has information relating events and risks (many to many relationship).
I'm trying to get all the risks from Riesgos, but also the events related to the risks from (. I'm using ADODB to query the sheets as database tables and using the following SQL:
SELECT * FROM [Riesgos$] r
LEFT JOIN [EventosRiesgos$] er ON r.[Id]=er.[Id Riesgo]
LEFT JOIN [Eventos$] e ON er.[Id Evento]=e.[Id]
But i get an error, it's in Spanish but a rough translation would be: Syntax error (missing operator) in expression "r.[Id]=er.[Id Riesgo] LEFT JOIN [Eventos$] e ON er.[Id Evento]=e.[Id]"
When I run the query only using the first 2 lines (only one join) everything works as expected. My question is: Why is the query not working when I use the two JOINs?
Can anyone help me, at least to find documentation on the use of ADODB to query Excel sheets?
Access Jet/ADODB/ACE likes brackets with multiple tables
SELECT * FROM ( [Riesgos$] r
LEFT JOIN [EventosRiesgos$] er ON r.[Id]=er.[Id Riesgo] )
LEFT JOIN [Eventos$] e ON er.[Id Evento]=e.[Id]
The only difference is brackets around the [riesgos$] r .... er.[Id Riesggo]

Access query returns empty fields depending on how table is linked

I've got an Access MDB I use for reporting that has linked table views from SQL Server 2005. I built a query that retrieves information off of a PO table and categorizes the line item depending on information from another table. I'm relatively certain the query was fine until approximately a month ago when we shifted from compatibility mode 80 to 90 on the Server as required by our primary application (which creates the data). I can't say this with 100% certainty, but that is the only major change made in the past 90 days. We noticed that suddenly data was not showing up in the query making the reports look odd.
This is a copy of the failing query:
SELECT dbo_porel.jobnum, dbo_joboper.opcode, dbo_porel.jobseqtype,
dbo_opmaster.shortchar01,
dbo_porel.ponum, dbo_porel.poline, dbo_podetail.unitcost
FROM ((dbo_porel
LEFT JOIN dbo_joboper ON (dbo_porel.assemblyseq = dbo_joboper.assemblyseq)
AND (dbo_porel.jobseq = dbo_joboper.oprseq)
AND (dbo_porel.jobnum = dbo_joboper.jobnum))
LEFT JOIN dbo_opmaster ON dbo_joboper.opcode = dbo_opmaster.opcode)
LEFT JOIN dbo_podetail ON (dbo_porel.poline = dbo_podetail.poline)
AND (dbo_porel.ponum = dbo_podetail.ponum)
WHERE (dbo_porel.jobnum="367000003")
It returns the following:
jobnum opcode jobseqtype shortchar01 ponum poline unitcost
367000003 S 6624 2 15
The query normally should have displayed a value for opcode and shortchar01. If I remove the linked table dbo_podetail, it properly displays data for these fields (although I obviously don't have unitcost anymore). At first I thought it might be a data issue, but I found if I nested the query and then linked the table, it worked fine.
For example the following code works perfectly:
SELECT qryTest.*, dbo_podetail.unitcost
FROM (
SELECT dbo_porel.jobnum, dbo_joboper.opcode, dbo_porel.jobseqtype,
dbo_opmaster.shortchar01, dbo_porel.ponum, dbo_porel.poline
FROM (dbo_porel
LEFT JOIN dbo_joboper ON (dbo_porel.jobnum=dbo_joboper.jobnum)
AND (dbo_porel.jobseq=dbo_joboper.oprseq)
AND (dbo_porel.assemblyseq=dbo_joboper.assemblyseq))
LEFT JOIN dbo_opmaster ON dbo_joboper.opcode=dbo_opmaster.opcode
WHERE (dbo_porel.jobnum="367000003")
) As qryTest
LEFT JOIN dbo_podetail ON (qryTest.poline = dbo_podetail.poline)
AND (qryTest.ponum = dbo_podetail.ponum)
I'm at a loss for why it works in the latter case and not in the first case. Worse yet, it seems to work intermittently for some records and not for others (it's consistent about the ones it does and does not work for).
Do any of you experts have any ideas?
You definitely need to use subqueries for multiple left/right joins in Access.
I think it's a limitation of the Jet optimizer that gets confused if you're just chaining left/right joins.
You can see that this is a recurrent problem that surfaces often.
I'm always confused by Access' use of brackets in joins. Try stripping out the extra brackets.
FROM
dbo_porel
LEFT JOIN
dbo_joboper ON (dbo_porel.assemblyseq = dbo_joboper.assemblyseq)
AND (dbo_porel.jobseq = dbo_joboper.oprseq)
AND (dbo_porel.jobnum = dbo_joboper.jobnum)
LEFT JOIN
dbo_opmaster ON (dbo_joboper.opcode = dbo_opmaster.opcode)
LEFT JOIN
dbo_podetail ON (dbo_porel.poline = dbo_podetail.poline)
AND (dbo_porel.ponum = dbo_podetail.ponum)
OK the above doesn't work - Sorry I give up