LEFT JOINing on additional criteria in MS Access - sql

I have the following T-SQL query (a simple test case) running fine in MS SQL but cannot get the equivalent query in MS Access (JET-SQL). The problem is the additional criteria in the LEFT JOIN. How can I do this in MS Access?
T-SQL:
SELECT * FROM A
LEFT OUTER JOIN B ON A.ID = B.A_ID
AND B.F_ID = 3
JET-SQL (what I have so far but crashes Access!):
SELECT * FROM dbo_A
LEFT JOIN dbo_B ON (dbo_A.ID = dbo_B.A_ID AND dbo_B.F_ID = 3)

You need to use a subselect to apply the condition:
SELECT *
FROM dbo_A LEFT JOIN
[SELECT dbo_B.* FROM dbo_B WHERE dbo_B.F_ID = 3]. AS dbo_B
ON dbo_A.ID = dbo_B.A_ID;
If you're running Access with "SQL 92" compatibility mode turned on, you can do the more standard:
SELECT *
FROM dbo_A LEFT JOIN
(SELECT dbo_B.* FROM dbo_B WHERE dbo_B.F_ID = 3) AS dbo_B
ON dbo_A.ID = dbo_B.A_ID;
Do you need this to be editable in Access? If not, just use a passthrough query with the native T-SQL. If so, I would likely create a server-side view for this, and I'd especially want to move it server-side if the literal value is something you would parameterize (i.e., the F_ID=3 is really F_ID=N where N is a value chosen at runtime).
BTW, I write these subselect derived table SQL statements every single day while working in Access. It's not that big a deal.

Do you get an error message when it crashes or does it just lock up? Judging by the dbo_B name I'm going to guess that these are linked tables in Access. I believe that when you do a join like that Access doesn't tell SQL server that it needs the result of the join, it says, "Give me all of the rows of both tables" then it tries to join them itself. If the tables are very large this can cause the application to lock up.
You're probably better off creating a view on SQL Server for what you need.

I think ms access expect to both tables name in each section of Joins ON clause. As a trick this work for me:
SELECT * FROM A
LEFT OUTER JOIN B ON A.ID = B.A_ID
AND B.F_ID = IIF(True, 3, A.ID)
A.ID or any other else field from table A

That last condition technically isn't a join but a comparison to a literal value. Put it in a WHERE clause:
SELECT *
FROM a LEFT OUTER JOIN b ON a.ID = b.a_id
WHERE b.f_id = 3;

Related

Translating MS Access Query for SQL Server

I am trying to recreate a query that was done in MS Access, and now is being handled in a SQL Server environment. I understand that some of the SQL syntax is different in Access than it is in SQL Server. Is there somewhere online that points out the main differences, or will help translate one to the other?
This is a query that I need to update to use in SQL Server:
UPDATE
dbo.TPR00100
INNER JOIN (
dbo.UPR10302
LEFT JOIN dbo.B3980280 ON dbo.TPR10302.COMPTRNM = dbo.B3980280.COMPTRNM
) ON dbo.TPR00100.STAFFID = dbo.TPR10302.STAFFID
SET
dbo.B3980280.COMPTRNM = dbo.TPR10302.comptrnm,
dbo.B3980280.BI_LOC_ID = dbo.TPR00100.locatnid
WHERE
(((dbo.B3980280.COMPTRNM) Is Null))
What are they key aspects that need to be handled differently in a SQL Server transaction for this query?
If find it handy to use an updateable CTE for this:
with cte as (
select
b39.comptrnm b39_comptrnm
b39.bssi_loc_id b39_bssi_loc_id,
tpr.comptrnm tpr_comptrnm,
tpr.locatnid tpr_locatnid
from dbo.tpr00100 tpr
inner join dbo.upr10302 upr on tpr.staffid = upr.staffid
inner join dbo.b3980280 b39 on tpr.comptrnm = b39.comptrnm
where b39_comptrnm is null
)
update cte
set b39_comptrnm = tpr_comptrnm, b39_bssi_loc_id = tpr_locatnid
Note: I am not really sure why the table to update is left joined in the original query, so I turned it to an `inner join .

Left join Ignore

I have recently noticed that SQL Server 2016 appears to be ignoring left joins if any column is not used in the select or where clause. Also not found in Actual execution plan.
This is good for if anyone added extra join but still not affecting performance.
I have query that took 9 sec, if I add column in select clause for Left join tables but without that only 1 sec.
Can anyone please check and suggest, Is that true or not?
Query with Actual execution plan. You can see there is no any table from left join in execution plan.
I'm not 100% sure what the question is asking, but a SQL optimizer can ignore left join. Consider this type of query:
select a.*
from a left join
b
on a.b_id = b.id;
If b.id is declared as unique (or equivalently a primary key) then the above query returns exactly the same result set as:
select a.*
from a;
I am not per se aware that SQL Server started putting this optimization in 2016. But the optimization is perfectly valid and (I believe) other optimizers do implement it.
Remember, SQL is a declarative language, not a procedural language. The SQL query describes the result set, not how it is produced.
If you have a left join and your matching condition don't return any data from the joined table it will return data as inner join return, when select statement does not contains columns from right tables. Not only in ms server 2016 but most of the DB's.
Left join reduces the performance of the query if there are large amount of data available in join tables.

MS Access, how to replace a saved query by the full query in a subquery

I have 3 tables:
1 - tblMembers_Info
2 - a junction table
3 - tblCourses
I need to query the members who haven't done a specific course.
After trying to do it manually I gave MS Access "Query Wizard" a try. I ended up with :
A saved query as Query1:
// That one query who did the course
SELECT tblMembers_Info.*, tblCourses.CourseName
FROM tblMembers_Info
INNER JOIN
(tblCourses INNER JOIN tblMembers_Courses
ON tblCourses.IDCourses = tblMembers_Courses.IDCourses)
ON tblMembers_Info.Members_ID = tblMembers_Courses.Members_ID
WHERE (tblCourses.CourseName) In ('NameOftheCourse');
2nd query using the saved Query1:
SELECT tblMembers_Info.Members_ID, tblMembers_Info.FirstName, tblMembers_Info.LastName
FROM tblMembers_Info
LEFT JOIN [Query1]
ON tblMembers_Info.[Members_ID] = Query1.[Members_ID]
WHERE (((Query1.Members_ID) Is Null));
How can I replace the Query1 in the second query with the full query instead of using a QueryDef (the saved query "Query1")?
Also, there's a better way for sure to write that query, I would really appreciate any help.
You can simply replace LEFT JOIN [Query1] with LEFT JOIN (...) AS [Query1] where ... should be the SQL of the first query, without the ending ;.
But I think in your specific case the use of NOT IN might give a better performance to get the same results:
SELECT tblMembers_Info.Members_ID, tblMembers_Info.FirstName, tblMembers_Info.LastName
FROM tblMembers_Info
WHERE tblMembers_Info.[Members_ID] NOT IN (
SELECT tblMembers_Info.[Members_ID]
FROM ((tblMembers_Info
INNER JOIN tblMembers_Courses
ON tblMembers_Info.Members_ID = tblMembers_Courses.Members_ID)
INNER JOIN tblCourses
ON tblCourses.IDCourses = tblMembers_Courses.IDCourses)
WHERE tblCourses.CourseName = 'NameOftheCourse'
);

Basic SQL join question. Can you help me improve my skillset?

Ok.. So I'm trying to improve my SQL skills and have a question. Here is a screen shot of the schema.
Schema http://img509.imageshack.us/img509/97/screenhunter02nov121946.gif
(http://img509.imageshack.us/img509/97/screenhunter02nov121946.gif)
Alright so I'm selecting a bunch of Report Bundles and other rows from a table you can see. I've got these two tables joining together correctly and displaying what should be returned. Now I need to add another field onto my result rows that states what type of report this is. How can I join up to the ReportGroupType table through the ReportBundleGroup table without getting a shwack of results?
Here is the query I am using so far.
SELECT *
FROM ReportBundleCustomerVisibility INNER JOIN ReportBundle
ON ReportBundleCustomerVisibility.ReportBundleID = ReportBundle.ID
WHERE ReportBundleCustomerVisibility.ReferenceCustomerID = 2303
Thanks again SO
SELECT *
FROM ReportBundleCustomerVisibility AS v
JOIN ReportBundle AS b ON b.ID = v.ReportBundleID
JOIN ReportBundleGroup AS g ON b.ID = g.ReportBundleID
JOIN ReportGroupTYpe AS t ON t.ID = g.ReportGroupTypeID
WHERE v.ReferenceCustomerID = 2303
It sounds like you just need another inner join to get the information you need. You can think about the second join as joining the result of the join with the ReportGroupType table. I added parenthesis to try to join the two sets the second INNER JOIN is operating on.
SELECT * FROM ((ReportBundleCustomerVisibility
INNER JOIN ReportBundle ON ReportBundleCustomerVisibility.ReportBundleID = ReportBundle.ID)
INNER JOIN ReportGroupType ON ReportBundleGroup.ReportGroupTypeID = ReportGroupType.ID)
WHERE ReportBundleCustomerVisibility.ReferenceCustomerID = 2303
I also highly suggest against using "SELECT *" in production code or any query you plan on reusing as the table schema can change and possibly effect reports and UI. Explicitly specify the columns instead.

What does (+) do in Oracle SQL?

I'm using Oracle SQL Developer to query an Oracle DB (not sure which version it is) and I'm going to use the SQL I make for a Crystal report. Many of the reports the previous developers have written don't use JOIN keywords to make the joins (and I'm not too familiar with JOIN keywords as a result).
Many of the joins they make are made in the WHERE statement. I'll notice something like this.
Select * From TableA, TableB WHERE TableA.PrimaryKey(+) = TableB.ForeignKey
My question is concerning the (+). What purpose does it serve and how do I use it in my code?
It is not recommended. See this previous answer
Difference between Oracle's plus (+) notation and ansi JOIN notation?
That represents a “right outer join” (right because the = is on the right side of the +).
SELECT *
FROM TableA, TableB
WHERE TableA.PrimaryKey(+) = TableB.ForeignKey
is equivalent to
SELECT *
FROM TableA
RIGHT OUTER JOIN TableB
ON (TableA.PrimaryKey = TableB.ForeignKey)
right outer join
(+) is used to perform right outer join in Oracle
RIGHT OUTER JOIN is one of the JOIN operations that allow you to specify a JOIN clause
For details
http://docs.oracle.com/javadb/10.8.3.0/ref/rrefsqlj57522.html