Select two columns one join - sql

Given this SQL query:
select A.field1 as field
from A left join B
on A.field1 = B.field1
union all
select A.field2 as field
from A left join B
on A.field2 = B.field1;
Is there some way to get the same with few lines? i.e: is there another way to get two columns from a table A joined each one separated with a column from the table B, and then both put into the same resultset column?
The reason for needing that is the real query has a more complex join and where conditions, and for that is a bit big and, almost all, redundant.
Thank you in advance!

With the left join and assuming that the join to B doesn't produce duplicates, then your query is more simply written as:
select A.field1 as field from A
union all
select A.field2 from A;
The left join to B doesn't do anything in this case.
I assume your query is more complicated or you intend an inner join. You could do the union all before the join:
select A.field
from (select field1 from A union all
select field2 from A
) a join
B
on A.field = B.field1 ;
Whether or not this has worse or the same performance depends on the nature of the data.

Related

get all rows from A plus missing rows from B

This seems so obvious but I am failing.
In Teradata SQL, how to get all rows from table A, plus those from table B, that do not occur in table A, based on key field key?
This must have been asked a thousand times. But honestly I do not find the answer.
Full outer join seems to give me duplicate "inner join" results.
--Edit , based on first comment (thanks) --
so if I would do
select * from A
union all
select * from B
left join A
on A.key = B.key
where A.key IS NULL
I guess that would work (untested) but is that the most performant way?
Sometimes EXISTS or NOT EXISTS performs better than joins:
select * from A
union all
select * from B
where not exists (
select 1 from A
where A.key = B.key
)
I assume the key columns are already indexed.
Your version is fine . . . if you select the right columns:
select A.* from A
union all
select B.*
from B left join
A
on A.key = B.key
where A.key IS NULL;
I think Teradata does a good job optimizing joins. That said, EXISTS is also a very reasonable option.

join or merge two table based on id merge

I have two tables:
I am looking for the results like mentioned in the last.
I tried union (only similar col can be merged), left join, right join i am getting repeated fields in Null areas what can be other options where i can get null without column repeating
A full join would get all results from both tables.
select
A.ID,
A.ColA,
A.ColB,
B.ColC,
B.ColD
from TableA A
full join Table B on A.ID = B.ID
Here is a good post to understand joins
You can try distinct:
select distinct * from
tableA a,
tableB b
where a.id = b.id;
It will not give any duplicate tuples.

AND/OR statements in SQL JOIN

I have two tables: table1 and table2. I can join them using id1 or id2. I prefer to use id1, but as in some rows id1 is missing, so I have to use id2. Is the following syntax correct:
SELECT *
FROM table1 as a
LEFT JOIN table2 as b
ON (a.id1 is not null and a.id1 = b.id1) or
(a.id2 is not null and a.id2 = b.id2)
It returns some results but I want to be sure if it is valid as I haven't seen it used before.
Are there better ways to do this?
Looks like you have a decent answer in the comments, but to toss another possibility into the ring, you could run both queries and union them.
select *
from table1 as a
LEFT JOIN table2 as b
on a.id1 = b.id1
union
select *
from table1 as a
LEFT JOIN table2 as b
on a.id2 = b.id2
The union will eliminate any duplicates between the sets, and will return records where either condition is true, much like your or statement. Performance wise, the union is probably a little slower, but gives you easier control over the sets. For instance if you only want set 2 to return results when id1 is null, just add it to the where clause. Anyway hope that helps.

Restricting a LEFT JOIN

I have a table, let's call it "a" that is used in a left join in a view that involves a lot of tables. However, I only want to return rows of "a" if they also join with another table "b". So the existing code looks like
SELECT ....
FROM main ...
...
LEFT JOIN a ON (main.col2 = a.col2)
but it's returning too many rows, specifically ones where a doesn't have a match in b. I tried
SELECT ...
FROM main ...
...
LEFT JOIN (
SELECT a.col1, a.col2
FROM a
JOIN b ON (a.col3 = b.col3)) ON (a.col2 = main.col2)
which gives me the correct results but unfortunately "EXPLAIN PLAN" tells that doing it this way ends up forcing a full table scan of both a and b, which is making things quite slow. One of my co-workers suggested another LEFT JOIN on b, but that doesn't work because it gives me the b row when it's present, but doesn't stop returning the rows from a that don't have a match in b.
Is there any way to put the main.col2 condition in the sub-SELECT, which would get rid of the full table scans? Or some other way to do what I want?
SELECT ...
FROM ....
LEFT JOIN ( a INNER JOIN b ON .... ) ON ....
add a where (main.col2 = a.col2)
just do a join instead of a left join.
What if you created a view that gets you the "a" to "b" join, then do your left joins to that view?
Select ...
From Main
Left Join a on main.col2 = a.col2
where a.col3 in (select b.col3 from b) or a.col3 is null
you may also need to do some indexing on a.col3 and b.col3
First define your query between table "a" and "b" to make sure it is returning the rows you want:
Select
a.field1,
a.field2,
b.field3
from
table_a a
JOIN table_b b
on (b.someid = a.someid)
then put that in as a sub-query of your main query:
select
m.field1,
m.field2,
m.field3,
a.field1 as a_field1,
b.field1 as b_field1
from
Table_main m
LEFT OUTER JOIN
(
Select
a.field1,
a.field2,
b.field3
from
table_a a
JOIN table_b b
on (b.someid = a.someid)
) sq
on (sq.field1 = m.field1)
that should do it.
Ahh, missed the performance problem note - what I usually end up doing is putting the query from the view in a stored procedure, so I can generate the sub-queries to temp tables and put indexes on them. Suprisingly faster than you would expect. :-)

How can I implement SQL INTERSECT and MINUS operations in MS Access

I have researched and haven't found a way to run INTERSECT and MINUS operations in MS Access. Does any way exist
INTERSECT is an inner join. MINUS is an outer join, where you choose only the records that don't exist in the other table.
INTERSECT
select distinct
a.*
from
a
inner join b on a.id = b.id
MINUS
select distinct
a.*
from
a
left outer join b on a.id = b.id
where
b.id is null
If you edit your original question and post some sample data then an example can be given.
EDIT: Forgot to add in the distinct to the queries.
INTERSECT is NOT an INNER JOIN. They're different. An INNER JOIN will give you duplicate rows in cases where INTERSECT WILL not. You can get equivalent results by:
SELECT DISTINCT a.*
FROM a
INNER JOIN b
on a.PK = b.PK
Note that PK must be the primary key column or columns. If there is no PK on the table (BAD!), you must write it like so:
SELECT DISTINCT a.*
FROM a
INNER JOIN b
ON a.Col1 = b.Col1
AND a.Col2 = b.Col2
AND a.Col3 = b.Col3 ...
With MINUS, you can do the same thing, but with a LEFT JOIN, and a WHERE condition checking for null on one of table b's non-nullable columns (preferably the primary key).
SELECT DISTINCT a.*
FROM a
LEFT JOIN b
on a.PK = b.PK
WHERE b.PK IS NULL
That should do it.
They're done through JOINs. The old fashioned way :)
For INTERSECT, you can use an INNER JOIN. Pretty straightforward. Just need to use a GROUP BY or DISTINCT if you have don't have a pure one-to-one relationship going on. Otherwise, as others had mentioned, you can get more results than you'd expect.
For MINUS, you can use a LEFT JOIN and use the WHERE to limit it so you're only getting back rows from your main table that don't have a match with the LEFT JOINed table.
Easy peasy.
Unfortunately MINUS is not supported in MS Access - one workaround would be to create three queries, one with the full dataset, one that pulls the rows you want to filter out, and a third that left joins the two tables and only pulls records that only exist in your full dataset.
Same thing goes for INTERSECT, except you would be doing it via an inner join and only returning records that exist in both.
No MINUS in Access, but you can use a subquery.
SELECT DISTINCT a.*
FROM a
WHERE a.PK NOT IN (SELECT DISTINCT b.pk FROM b)
I believe this one does the MINUS
SELECT DISTINCT
a.CustomerID,
b.CustomerID
FROM
tblCustomers a
LEFT JOIN
[Copy Of tblCustomers] b
ON
a.CustomerID = b.CustomerID
WHERE
b.CustomerID IS NULL