Select from 2 tables with a left join - sql

Here is probably an easy one if your used to SQL, which I'm not.
I have this query:
SELECT *
FROM myTable
LEFT JOIN anotherTable
ON myTable.myField=anotherTable.anotherField
Actually, this query returns everything from myTable which meets the join condition (as far as my comprehension goes). This query works great, but I would like to select another field from another table. What I would like to do is something like this:
SELECT myTable.*, myTable2.aSpecificField
FROM myTable, myTable2
LEFT JOIN anotherTable
ON myTable.myField=anotherTable.anotherField
WHERE myTable.id = myTable2.id
However, this doesn't work, I get an error message about the LEFT JOIN. I would like the aSpecificField from myTable2 to be added to the rows where the ID of both tables match.
Can you help me building this query correctly? Thank you.

The Microsoft Access query design window lets you use wizards or drag-and-drop to create queries. You can then tidy up the SQL in design view. Add your tables to the design grid, drag the joining fields from one table to the next, and then select the fields you want.
When you wish to advance your knowledge of Access SQL, you can read ...
These are for Jet (<2007), but ACE (>=2007) is not that different as regards SQL
Fundamental Microsoft Jet SQL for Access 2000
Intermediate Microsoft Jet SQL for Access 2000
Advanced Microsoft Jet SQL for Access 2000
Jet Database Engine
Background on design
Fundamentals of Relational Database Design, Paul Litwin, 2003
An often recommended MS Access book
Access cookbook

List out your fields rather then using *. Like so:
SELECT m.Field1, m.Field2, m2.Field1 FROM
MyTable m LEFT JOIN MyTable2 m2 ON m2.ID=m1.ID
Per your comment what relation does table3 have with another table?
Just include it based on that relationship
SELECT m.Field1, m.Field2, m2.Field1, m3.Field1 FROM
MyTable m LEFT JOIN MyTable2 m2 ON m2.ID=m1.ID LEFT JOIN MyTable3 m3 ON m3.ID=m2.ID

So you want to return the rows where the ids match for both tables? And not where they dont match? So not a left or right join but a plain join?
Select tab1.*,tab2.* from mytable tab1
INNER JOIN mytable2 tab2
ON tab1.id = tab2.otherid
Or if you have 3 tables to join?
Select tab1.*,tab2.*,tab3.* from mytable tab1
INNER JOIN mytable2 tab2
ON tab1.id = tab2.otherid
INNER JOIN mytable3 tab3
ON tab1.id = tab3.anotherid
Replace tabX.* with specific fields if needed?

Related

Access SQL FROM IN and JOINS

I've been successfully using
SELECT [field] FROM [Table] IN 'Network Location';
this question filled me in on that
Access SQL Query from another DB
My question is: How does a JOIN fit into this framework
Is it
SELECT [field]
FROM [Table] IN 'Network Location'
JOIN [Table2]
ON [Table2].field = [Table].field;
or
SELECT [field]
FROM [Table]
JOIN [Table2]
ON [Table2].field = [Table].field IN 'Network Location' ;
it feels like the former is the correct one. SQL statements are supposed to be like sentences and that one feels most appropriately ordered.
Consider the bracketed or backticked name qualifier to query from external Access databases. Semantically, this would follow other RBDMS' (e.g., Oracle, Postgres, SQL Server, MySQL, SQLite) period qualifiers to query across clusters, schemas, databases on same machine/server. From there use table aliases for referencing in SELECT, JOIN, WHERE, and other clauses.
SELECT t1.[field]
FROM [C:\Path\To\External\myDatabase.accdb].[Table] t1
INNER JOIN [Table2] t2
ON t2.field = t1.field;
SELECT t1.`field`
FROM `C:\Path\To\External\myDatabase.accdb`.`Table` t1
INNER JOIN `Table2` t2
ON t2.field = t1.field;
Do note, Access requires JOIN to be specific: INNER, LEFT, RIGHT.
And thanks to the JET/ACE SQL engine, you can even query Excel workbooks and CSV files in similar manner assuming data is contiguous in a table-like range:
SELECT *
FROM [Excel 12.0 Xml;HDR=Yes;Database=C:\Path\To\myWorkbook.xlsx].[SheetName$] AS t;
SELECT t.*
FROM [text;database=C:\Path\To\Folder].myFile.csv AS t;

Simple way to join many tables with similar names in SSMS?

I have many tables that are all named similarly (like "table1" "table2" "table3" etc.) and I need to use all of them in a query. They all contain the same two variables ("ID" and "date") that they are joined on.
There are at least 25 tables of this sort and I have read-only access to the database so I can't combine them or even create a view that would do so.
My question is: Is there a simple shortcut I can use to join all these tables? If this were SAS I would create a macro, but I'm using Microsoft SQL Server Management Studio 2012.
Instead of having to do this:
select *
from table1 a
join table2 b on a.id=b.id and a.date=b.date
join table3 c on b.id=c.id and b.date=c.date
join ....
join ....
join table25 y on x.id=y.id and x.date=y.date
I'd like to do something like:
select *
from merge(table1 - table25) using(id, date)
Replacing the "merge" statement above with whatever is appropriate. Is such a thing possible?
As pointed out in the comments, the succinct syntax you are looking for doesn't exist.
The only way to shorten the SQL that takes advantage of the fact that the joining columns are all named the same would involve using the using keyword:
select *
from table1 a
join table2 b using (id, date)
join table3 c using (id, date)
join ....
join ....
join table25 y using (id, date)
But sadly, even that won't work for you, because the using keyword is not recognized in SQL Server. It does work in other popular databases though.

Select all fields from table A but single field from B?

Is there a way in ABAP's OpenSQL to simplify the select columns in a JOIN when I want to grab all the fields of one table but only selected fields from the other table(s)?
For instance, in mysql we can simply do:
SELECT tb1.*, tb2.b, tb2.d
FROM tableA tb1
INNER JOIN tableB tb2 ON tb1.x = tb2.a
However, OpenSQL does not seem to allow selecting tb1~*, tb2~b, tb2~d so I have to resort to this:
SELECT tb1.x, tb1.y, tb1.z, tb2.b, tb2.d
FROM tableA tb1
INNER JOIN tableB tb2 ON tb1.x = tb2.a
For very large tables, especially standard tables, this becomes unwieldy, difficult to read and more annoying to maintain.
Is there a better way to select all fields of tb1 and some fields from tb2?
Yes, this is possible in the OpenSQL from 7.40 SP08. See this article.
The quotation from the article has that.
Column Specification
In the SELECT list, you can specify all columns of a data source using the syntax data_source~* from 7.40, SP08 on. This can be handy when working with joins.
SELECT scarr~carrname, spfli~*, scarr~url
FROM scarr INNER JOIN spfli ON scarr~carrid = spfli~carrid
INTO TABLE #DATA(result).
In the previous versions unfortunately one has to specify the columns one by one or use database native SQL for example with ADBC.

Having issues using a Right Join in MS Access 2010 with two tables that have the same fields

I have two tables, Table A and Table B. Each table have 4 fields, the name of the fields are the same for both. Both tables are extracted from other tables, and each record acts as a primary key.
I want to write a query in MS Access 2010 that gets the data unique to Table B and not shared with Table A. I am using the following image as a reference, and it looks like I need to do a Right Join.
Hello. There is something not right with my SQL, I've tested it and I am getting the incorrect result. Below is the closest I've gotten:
SELECT DISTINCT TableB.*
FROM TableB RIGHT JOIN TableA ON (TableB.Field1 = TableA.Field1) AND (TableB.Field2 = TableA.Field2) AND (TableB.Field3 = TableA.Field3) AND (TableB.Field4 = TableA.Field4)
WHERE (((TableA.Field1) Is Null));
I think it would be clearer for you to use not exists:
select tableb.*
from tableb
where not exists (select 1
from tablea
where (TableB.Field1 = TableA.Field1) AND (TableB.Field2 = TableA.Field2) AND (TableB.Field3 = TableA.Field3) AND (TableB.Field4 = TableA.Field4)
);
Your use of RIGHT JOIN is incorrect. As phrased, you want a LEFT JOIN. That is, you want to keep all rows in the first table (the "left" table in the JOIN) regardless of whether or not a match exists in the second table. However, the NOT EXISTS does the same thing and the logic is a bit clearer.
You want to have right join if tablea is in your select statement, but as you have
SELECT DISTINCT TableB.*
you may want to have a left join instead. My suggestion would be changing your code from right to left join.
TableB acts like table A from venn diagrams above.

NESTED INNER JOIN using MS Access 2003 via ODBC

If this works:
SELECT COUNT(t1.ID) AS count FROM Project t1
INNER JOIN (SELECT DISTINCT t.Site,t.id FROM _Equipment_id t WHERE t.OEM LIKE '%ABC%') t2 ON t1.Site=t2.Site AND t1.id=t2.id
and this works:
SELECT COUNT(t3.ID) AS count FROM Wall t3
INNER JOIN Project t1 ON t3.Project_number=t1.Project_number
Why doesn't this work:
SELECT COUNT(t3.ID) AS count FROM Wall t3
INNER JOIN Project t1 ON t3.Project_number=t1.Project_number
INNER JOIN (SELECT DISTINCT t.Site,t.id FROM _Equipment_id t WHERE t.OEM LIKE '%ABC%') t2 ON t1.Site=t2.Site AND t1.id=t2.id
Ultimately, I have 10 tables like the Wall table that I am trying to get a total count from the first SELECT....
SELECT COUNT(t3.ID) AS count FROM Wall t3
INNER JOIN (Project t1
INNER JOIN (SELECT DISTINCT t.Site,t.id FROM _Equipment_id t WHERE t.OEM LIKE '%ABC%') t2
ON t1.Site=t2.Site AND t1.id=t2.id)
ON t3.Project_number=t1.Project_number
Maybe it's just a syntax error? Office Help at the bottom where they mention nesting. The other possibility is that the aliases are somehow scoped so that they are not available to the join, but I'm no expert on MS Access. Maybe you should just try dropping the aliases altogether.
You have a couple of minor issues with your code: a table name that starts with an underscore character (_Equipment_id) and an AS clause ("alias") that is a SQL keyword (AS count). When these are corrected, your SQL is valid SQL-92 syntax.
Sadly, the problem is that Access (ACE, Jet, whatever) does not support the SQL-92 Standard. Access insists that each nested JOIN clause is put in parentheses.
[Aside: JOINs in parentheses are allowed in Standard SQL because it can potentially change the query results. However Access, does not respect the order specified by the coder and allows itself to evaluate JOINs in order it sees fir. So not only Access's syntax non-compliant with the Standard, there is also a loss of functionality! However, this further problem with Access will have no ill effect for this particular query.]
You have two JOINs in the same scope here:
...
INNER JOIN Project t1 ON t3.Project_number=t1.Project_number
INNER JOIN
...
Your code needs to work around Access's problem by enclosing the JOIN in parentheses; because all your JOINs are INNER flavour, it probably doesn't matter where they go.
Also, as regards correcting your AS clause, Access again doesn't support Standard SQL's quoted identifiers (...AS "count"...) and insists you use its proprietary square brackets syntax (...AS [count]...) -- of course, you could choose a different name but there may exist application code that relies on it.
Code to workaround both Access problems:
SELECT COUNT(t3.ID) AS [count]
FROM (Wall t3
INNER JOIN Project AS t1
ON t3.Project_number = t1.Project_number)
INNER JOIN (
SELECT DISTINCT t.Site,t.id
FROM _Equipment_id AS t
WHERE t.OEM LIKE '%ABC%'
) AS t2
ON t1.Site = t2.Site
AND t1.id = t2.id;