When you join a table with a derived table, can the derived table query refer to columns from the other table in the join, and why?
Example :
SELECT
cr.CountryRegionCode,
cr.Name [Country Name],
crc.CurrencyCode
Currency cr
INNER JOIN
( -- there are 109 currency codes in CountryRegionCurrency
SELECT
[CountryRegionCode],
[CurrencyCode],
[ModifiedDate]
FROM [AdventureWorks2014].[Sales].[CountryRegionCurrency]
) crc ON cr.CountryRegionCode = crc.CountryRegionCode
Can the derived table query CRC refer to the columns of Currency ?
A derived table that is part of a JOIN cannot reference objects outside of the subquery's scope. A derived table that is part of an APPLY can reference columns outside of the subquery's scope.
Example:
SELECT *
FROM TableA A
CROSS JOIN (SELECT *
FROM TableB sq
WHERE A.ID = sq.A_ID) B;
This will fail, due to the object A not being defined with the scope of the subquery. The correct syntax for the above query would be this:
SELECT *
FROM TableA A
INNER JOIN (SELECT *
FROM TableB sq) B ON A.ID = B.A_ID;
On the other hand, if you were to use APPLY you could reference columns outside of the subquery's scope:
SELECT *
FROM TableA A
CROSS APPLY (SELECT *
FROM TableB sq
WHERE A.ID = sq.A_ID) B;
Edit: Not specific to the question, but it's worth noting that within a subquery if a column is not quantified then the column will always be assumed to reference the table in the subquery first. Let's assume, for example, that the columns to JOIN on are actually A.ID and B.ID. If you were therefore to do the below, it would work:
SELECT *
FROM TableA A
CROSS JOIN (SELECT *
FROM TableB sq
WHERE ID = ID) B;
That's because the WHERE might as well be WHERE B.ID = B.ID and B.ID is always going to equal the value of itself unless it has the value NULL.
It's therefore incredibly important to always quantify your columns.
Related
How to join two tables if a field contains other field? Example:
On table A I have a field with data '000;111;222' and on table B I have a field with data '111'.
I want to join like this:
select * from A join B on A.field contains B.field
You could do:
select a.*, b.*
from a
inner join b on b.field = any(string_to_array(a.field, ';'))
The join condition turns a.field to an array, then checks if it contains b.field.
Well perhaps you are giving string_to_array the incorrect parameters. As alternative you can use the POSITION function to find if there is a sbustring match.
with table_a (acol) as ( values('000;111;222'),('000;xxx;222') )
, table_b (bcol) as ( values ('111'),('xxx'),('000'),('123') )
select *
from table_a
join table_b on POSITION(bcol in acol) > 0;
I have this SQL problem: I have tables A and B. Table A has columns id and name, Table B amount and id which is a foreign key to table A.id.
I need to return all table A rows that don't have their id stored in table B. Any ideas?
So the complete opposite is:
SELECT *
FROM a
LEFT OUTER JOIN b ON a.id = b.id;
Here row what I need is left out of result
Just add a where clause:
SELECT a.*
FROM a LEFT OUTER JOIN
b
ON a.id = b.id
WHERE b.id IS NULL;
You can also use NOT EXISTS:
select a.*
from a
where not exists (select 1 from b where b.id = a.id);
In most databases, the two methods typically have similar performance.
Lets say I have a query where one field can appear in either Table A or Table B but not both. So to retrieve it I use Coalesce.
Something like
Select
...
Coalesce(A.Number,B.Number) Number
...
From Table A
Left Join Table B on A.C= B.C
Now lets say I want to join another table to that Number field
should I just do
Join Table Z on Z.Z = Coalesce(A.Number,B.Number)
Or is it better to wrap my original table in a query and join on the definite result. So something like
Select * from (
Select
...
Coalesce(A.Number,B.Number) Number
...
From Table A
Left Join Table B on A.C= B.C
) T
left join Table Z on Z.Number= T.Number
Does this make a difference?
if i were joining another table to the result of the first query instead of a sub query i would place the first part in a CTE whenever possible, i believe the performance would be the same as a subquery but CTEs are more readable in my opinion.
with cte1 as
(
Select
...
Coalesce(A.Number,B.Number) Number
...
From Table A
Left Join Table B
on A.C= B.C
)
select *
from cte1 a
Join Table Z
on Z.Z = a.number
How can we use reference of main query result set as a source table in subquery
Table A, Table C
Select
(Select * From a)
From
(Select tabA.*
From A tabA
Join C tabC
On tabA.id = tabC.id) as a
I got invalid object a error here
Presumably, you want a common table expression (CTE):
with a as (
select tabA.*
from A tabA Join
C tabC
on tabA.id = tabC.id
)
Select (Select * from a)
From a;
That said, your query makes no sense. The scalar subquery is probably going to be returning an error, either because of the number of rows or number of columns.
if you using sqlserver than modified your query based on below query.
select * from
(select A.* from TableA A inner join TableB B on A.EmployeeID = B.EmployeeID ) a
SQL:
WITH joined AS (
SELECT *
FROM table_a a
JOIN table_b b ON (a.a_id = b.a_id)
)
SELECT a_id
FROM joined
returns invalid identifier.
How can you select joined column when using WITH clause? I have tried aliases, prefixing and nothing worked. I know I can use:
WITH joined AS (
SELECT a.a_id
FROM table_a a
JOIN table_b b ON (a.a_id = b.a_id)
)
SELECT a_id
FROM joined
but I need this alias to cover all fields.
Only way I managed to meet this condition is using:
WITH joined AS (
SELECT a.a_id a_id_alias, a.*, b.*
FROM table_a a
JOIN table_b b ON (a.a_id = b.a_id)
)
SELECT a_id_alias
FROM joined
but it is not perfect solution...
You can use the effect of the USING clause when joining the tables.
When you join tables where the join columns have the same name (as it is the case with your example), the USING clause will return the join column only once, so the following works:
with joined as (
select *
from table_a a
join table_b b using (a_id)
)
select a_id
from joined;
SQLFiddle example: http://sqlfiddle.com/#!4/e7e099/2
I don't think you can do this without aliases. The result of the "joined" query has two fields, both named a_id. Unless you alias one (or both), as you did in your final query, the outer query has no idea which a_id you are referring to.
Why is your final query not a "perfect" solution?
You can probably use alias as below:
WITH JOINED AS (
SELECT A.A_ID A_A_ID, B.A_ID B_A_ID,
A.FIELD_NAME1 A_FIELDNAME1, A.FIELDNAME2 A_FIELDNAME2,A.FIELDNAME_N A_FIELDNAME_N,
B.FIELD_NAME1 B_FIELDNAME1, B.FIELDNAME2 B_FIELDNAME2,B.FIELDNAME_N B_FIELDNAME_N,
FROM TABLE_A A
JOIN TABLE_B B ON (A.A_ID = B.A_ID)
)
SELECT A_A_ID, B_A_ID
FROM JOINED
IT IS ALWAYS A GOOD PRACTICE TO AVOID USING SELECT *