SQL Server Join: Full table vs selected column from table - sql

Just wondering.... what is the difference between
select
a.field1, b.field1
from
table1 a
inner join
table2 b on a.field2 = b.field2
and
select
a.field1, b.field1
from
table1 a
inner join
(select field1, field
from table2 ) b on a.field2 = b.field2
I've seen this SQL query in one of the legacy systems that I am currently handling. I checked out the execution plan immediately to compare but the results seems the same.
Sorry for being so ignorant. :)

I think we use this to optimise performance.
Refer your first query;
select a.field1, b.field1
from table1 a
inner join table2 b
on a.field2 = b.field2
Actually you have used only 2 columns in table2
(b.field1 to display and b.field2 to join the tables)
So no use of retrieving all the fields in table2.
If table2 consist of highly weighted columns (eg: image, blob) your query response time going to be slow.

Related

Left join not returning null records

I'am dealing with a pretty basic SQL query, but I cannot understand why the non matching records are not represented with the null values in right table.
I have table A and table B with a composite key and some data in table B that I know that they do not match the key in table A. However, the result set returns only rows with matching keys without non matching (null) records.
SELECT *
FROM TableA a LEFT JOIN
TableB b
ON a.Field1 = b.Field1 AND
a.Field2 = b.Field2
WHERE b.Field1 IS NULL
I was expecting to see records from table A and those records from table B that do not match to be represented by Nulls.
EDIT************************************************************
Link with sample data and tables:
https://drive.google.com/file/d/1PNlyqO4mwMBOGgQnWVlduiDKaDjSaE8v/view?usp=sharing
Last record in TableB should be seen because value for Field5 differs from value in TableA.
The problem with your attempt is that you start with the records in TableA then LEFT JOIN against TableB. This forces the engine to only display records from TableA, with additional rows/columns from TableB if they match, but not records from TableB that aren't on TableA.
Either you want to reverse the join order:
SELECT
*
FROM
TableB b
LEFT JOIN TableA a ON
a.Field1 = b.Field1 AND
a.Field2 = b.Field2
WHERE
a.Field1 IS NULL -- records from A table shouldn't exist
Or as RIGHT JOIN
SELECT
*
FROM TableA a RIGHT JOIN
TableB b
ON a.Field1 = b.Field1 AND
a.Field2 = b.Field2
WHERE a.Field1 IS NULL -- records from A table shouldn't exist
Or a FULL JOIN if you want records from both displayed, even if no match on the other table (no WHERE clause):
SELECT
*
FROM TableA a FULL JOIN
TableB b
ON a.Field1 = b.Field1 AND
a.Field2 = b.Field2
Your SQL assumes inner join when you put is null check to where clause. Try this:
SELECT *
FROM TableA a LEFT JOIN
TableB b
ON a.Field1 = b.Field1 AND
a.Field2 = b.Field2 AND
B.Field1 is null and B.Field2 is null <== Added.

Converting a PostgreSQL query with IN / NOT IN to JOINs

I currently have two tables with the same structure. Table A (as an example) has 10,000 rows, table B has 100,000 rows. I need to obtain the rows that are in Table B that are not in Table A, but only if certain fields are the same (and one is not).
Right now, the query is something like:
select *
from tableA A
where (A.field1, A.field2) in (select field1, field2 from tableB B)
and A.field3 not in (select field3 from B)
This works, but probably a better performant solution could be done with JOINs. I have tried to do it but all I get is a very huge list of duplicated rows. Could someone point me in the right direction?
Based on your current query this is what it translates to as joins:
select *
from tableA A
inner join tableB B on A.field1 = B.field1 and A.field2 = B.field2
left outer join tableB C on A.field3 = C.field3
where c.field3 is null
A faster query would be:
select A.pk
from tableA A
inner join tableB B on A.field1 = B.field1 and A.field2 = B.field2
left outer join tableB C on A.field3 = C.field3
where c.field3 is null
group by A.pk
This would give you the rows you need to add to tableB because they aren't found.
Or you can just get the fields you want to pull over:
select A.field1, A.field2, A.field3
from tableA A
inner join tableB B on A.field1 = B.field1 and A.field2 = B.field2
left outer join tableB C on A.field3 = C.field3
where c.field3 is null
group by A.field1, A.field2, A.field3
[NOT] EXISTS is your friend:
SELECT *
FROM tableA A
WHERE EXISTS ( SELECT * FROM tableB B
WHERE A.field1 = B.field1
AND A.field2 = B.field2
)
AND NOT EXISTS ( SELECT * FROM tableB B
WHERE A.field3 = B.field3
);
Note: if the joined columns are NOT NULLable, the [NOT] EXISTS() version will behave exactly the same as the [NOT] IN version
Reading the question text again (and again):
I need to obtain the rows that are in Table B that are not in Table A, but only if certain fields are the same (and one is not).
SELECT *
FROM tableB B
WHERE EXISTS ( SELECT * FROM tableA A
WHERE A.field1 = B.field1
AND A.field2 = B.field2
AND A.field3 <> B.field3
);

using where clause with Union

I have two tables, t1 and t2, with identical columns(id, desc) and data. But one of the columns, desc, might have different data for the same primary key, id.
I want to select all those rows from these two tables such that t1.desc != t2.desc
select a.id, b.desc
FROM (SELECT * FROM t1 AS a
UNION ALL
SELECT * FROM t2 AS b)
WHERE a.desc != b.desc
For example, if t1 has (1,'aaa') and (2,'bbb') and t2 has(1,'aaa') and (2,'bbb1') then the new table should have (2,'bbb') and (2,'bbb1')
However, this does not seem to work. Please let me know where I am going wrong and what is the right way to do it right.
Union is not going to compare the data.You need Join here
SELECT *
FROM t1 AS a
inner join t2 AS b
on a.id =b.id
and a.desc != b.desc
UNION ALL dumps all rows of the second part of the query after the rows produced by the first part of the query. You cannot compare a's fields to b's, because they belong to different rows.
What you are probably trying to do is locating records of t1 with ids matching these of t2, but different description. This can be achieved by a JOIN:
SELECT a.id, b.desc
FROM t1 AS a
JOIN t2 AS b ON a.id = b.id
WHERE a.desc != b.desc
This way records of t1 with IDs matching records of t2 would end up on the same row of joined data, allowing you to do the comparison of descriptions for inequality.
I want both the rows to be selected is the descriptions are not equal
You can use UNION ALL between two sets of rows obtained through join, with tables switching places, like this:
SELECT a.id, b.desc -- t1 is a, t2 is b
FROM t1 AS a
JOIN t2 AS b ON a.id = b.id
WHERE a.desc != b.desc
UNION ALL
SELECT a.id, b.desc -- t1 is b, t2 is a
FROM t2 AS a
JOIN t1 AS b ON a.id = b.id
WHERE a.desc != b.desc
The UNION operator is used to combine the result-set of two or more SELECT statements.
Notice that each SELECT statement within the UNION must have the same number of columns. The columns must also have similar data types.
So, if it has same number of columns and same datatype, then use Union otherwise join only Can be used.
SELECT *
FROM t1 AS a
inner join t2 AS b
on a.id =b.id
and a.desc != b.desc

What is this before a column in SQL?

I'm new to SQL and I am seeing a select that states SELECT something.columnName FROM Table.
I'm just wondering what the "something" is used for?
If you select from multiple tables in a single query then you can specify the table and column name you want to select. Example:
select table1.col1, table1,col2, table2.col5
from table1
join table2 on t1.id = t2.id
You can also specify alias names for tables or columns to make things shorter or if you join the same tables twice. Example:
select t1.col1 as A, t1.col2 as B, t2.col5 as C
from veryLongTableName1 t1
join veryLongTableName2 t2 on t1.id = t2.id
That is either a table name or an alias for a table name.
When joining tables, you might need to specify which table a field should be fetched from. Example:
select TableA.Name, TableB.Name
from TableA
inner join TableB on TableB.id = TableA.id
Example with aliases:
select a.Name, b.Name
from TableA as a
inner join TableB as b on b.id = a.id
It is a alias to show form wich table the column comes. You need this if you join to tables wich have a colum with the same name.

Join behavior when a table is not joined using its own key

If I have the query:
SELECT *
FROM Table1 a
Inner Join Table2 b on a.Key = b.Key
Inner Join Table3 c on a.Key = b.Key
What is happening? I recently made this error in some code (wanted instead to join c on on a.Key = c.Key), and while I discovered and fixed it, I was surprised it was allowed to execute and get a result.
I was curious what happens when such a query is called. From what I can tell, it executes a cross join between (table1 join table2) and table3?
Since it is a condition that is always true, it is equivalent to:
SELECT * FROM Table1 a
Inner Join Table2 b on a.Key=b.Key
Inner Join Table3 c on 1=1
;
,eg a cartesian product of (t1 join t2) * t3.