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

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.

Related

Best practice when joining two main non linked tables (no FK) by static id

I would like to combine data from two "main" tables in one single SQL query which I can not join via parent-child key link because non exists
Let's say I have main_table and (for the lack of any better name) main_table2
I can do this
SELECT * FROM main_table mt
LEFT JOIN optional_data ON mt.id = od.fk_mt_id
LEFT JOIN main_table mt2 on mt2.id=$some_id
$some_id is in variable defined in my code
I'm looking for your advice if the above is accepted as best practice of joining main_table2 which does not have any relationship with main_table or optional_data?
Are there any negative consequences when such join via variable occurs?
Do you think such requirement is a sign of incorrectly structured database?
If this is what you intend:
SELECT *
FROM main_table mt LEFT JOIN
optional_data od
ON mt.id = od.fk_mt_id LEFT JOIN
main_table mt2
ON mt2.id = $some_id;
(I added a table alias for od.)
Then I can only comment on the structure of the query.
Do not use SELECT *. By definition, you have columns with duplicated names because the same table appears twice in the FROM.
Do not munge query strings with constant values. $some_id should be passed in as a parameter.
You might be able to accomplish what you want in some other way, but your question doesn't provide enough information.

Joining multiple tables with single join clause (sqlite)

So I'm learning SQL (sqlite flavour) and looking through the sqlite JOIN-clause documentation, I figure that these two statements are valid:
SELECT *
FROM table1
JOIN (table2, table3) USING (id);
SELECT *
FROM table1
JOIN table2 USING (id)
JOIN table3 USING (id)
(or even, but that's beside the point:
SELECT *
FROM table1
JOIN (table 2 JOIN table3 USING id) USING id
)
Now I've seen the second one (chained join) a lot in SO questions on JOIN clauses, but rarely the first (grouped table-query). Both querys execute in SQLiteStudio for the non-simplified case.
A minimal example is provided here based on this code
CREATE TABLE table1 (
id INTEGER PRIMARY KEY,
field1 TEXT
)
WITHOUT ROWID;
CREATE TABLE table2 (
id INTEGER PRIMARY KEY,
field2 TEXT
)
WITHOUT ROWID;
CREATE TABLE table3 (
id INTEGER PRIMARY KEY,
field3 TEXT
)
WITHOUT ROWID;
INSERT INTO table1 (field1, id)
VALUES ('FOO0', 0),
('FOO1', 1),
('FOO2', 2),
('FOO3', 3);
INSERT INTO table2 (field2, id)
VALUES ('BAR0', 0),
('BAR2', 1),
('BAR3', 3);
INSERT INTO table3 (field3, id)
VALUES ('PIP0', 0),
('PIP1', 1),
('PIP2', 2);
SELECT *
FROM table1
JOIN (table2, table3) USING (id);
SELECT *
FROM table1
JOIN table2 USING (id)
JOIN table3 USING (id);
Could someone explain why one would use one over the other and if they are not equivalent for certain input data, provide an example? The first certainly looks cleaner (at least less redundant) to me.
INNER JOIN ON vs WHERE clause has been suggested as a possible duplicate. While it touches on the use of , as a join operator, I feel the questions and especially the answers are more focussed on the readability aspect and use of WHERE vs JOIN. My question is more about the general validity and possible differences in outcome (given the necessary input to induce the difference).
SQLite does not enforce a proper join syntax. It sees the join operator ([INNER] JOIN, LEFT [OUTER] JOIN, etc., even the comma of the outdated 1980s join syntax) separate from the condition (ON, USING). That is not good, because it makes joins more prone to errors. The SQLite docs are hence a very bad reference for learning joins. (And SQLite itself a bad system for learning them, because the DBMS doesn't detect standard SQL join violations.)
Stick to the syntax defined by the SQL standard (and don't ever use comma-separated joins):
FROM table [alias]
((([INNER] | [(LEFT|FULL) [OUTER]]) JOIN table [alias] (ON conditions | USING ( columns ))) | (CROSS JOIN table [alias]))
((([INNER] | [(LEFT|FULL) [OUTER]]) JOIN table [alias] (ON conditions | USING ( columns ))) | (CROSS JOIN table [alias]))
...
(Hope, I've got this right :-) And I also hope this is readable enough :-| I've omitted NATURAL JOIN and RIGHT [OUTER] JOIN here, because I don't recommend using them at all.)
For table you can place some table name or view or a subquery (the latter including parentheses, e.g. (select * from mytable)). Columns in USING have to be surrounded by parentheses (e.g. USING (a, b, c)). (You can of couse use parentheses around ON conditions as well, if you find this more readable.)
In your case, a properly written query would be:
SELECT *
FROM table1
JOIN table2 USING (id)
JOIN table3 USING (id)
or
SELECT *
FROM table1 t1
JOIN table2 t2 ON t2.id = t1.id
JOIN table3 t3 ON t3.id = t1.id
for instance. The example suggests three 1:1 related tables, though. In real life these are extremely rare and a more typical example would be
SELECT *
FROM table1 t1
JOIN table2 t2 ON t2.t1_id = t1.id
JOIN table3 t3 ON t3.t2_id = t2.id
After fixing syntax, these are not the same for all tables, read the syntax & definitions of the join operators in the manual. Comma is cross join with lower precedence than join keyword joins. Different DBMS's SQLs have syntax variations. Read the manual. Some allow naked join for cross join.
using returns only one column for each specified column name & natural is using for all common columns; but other joins are based on cross join & return a column for every input column. So since here tables 2 & 3 have id columns the comma returns a table with 2 id columns. Then using (id) doesn't make sense since one operand has 2 id columns.
If only tables 1 & 3 have an id column, clearly the 2nd query can't join 1 & 2 using id.
There are always many ways to express things. In particular SQL DBMSs execute many different expressions the same way. Research re relational query implementation/optimization in general, in SQL & in your DBMS manual. Generally no simple query variations like these make a difference in execution for the simplest query engine. (We see that in SQLite cross join "is handled differently by the query optimizer".)
First learn to write straightforward queries & learn what the operators do & what their syntax & restrictions are.

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.

What is the difference between JOIN USING and JOIN ON?

In general, is there any difference in result set or query performance between:
SELECT * FROM tableA JOIN tableB USING (id);
and
SELECT * FROM tableA ta JOIN tableB tb ON (ta.id = tb.id);
If so, what is the difference?
Pros / Cons to using one over the other?
When you say USING, then the columns are treated differently in the query:
Both tables must have the same columns and names for the join keys. (I think this is a good practice anyway, but USING requires it.)
The keys used for the join can only be used without a table alias in the rest of the query.
If you do SELECT *, then the join keys are only returned once.

Select from 2 tables with a left join

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?