I am using microsoft sql server and my query is of the following format (table1 primary key is (A,B)):
Select table1.A, table1.B, table2.C, Table3.D
from table1
left outer join table2 on table1.A = table2.A
left outer join tabl3 on table1.B = table3.B
//Here comes the question
//Except (A,B) in ( select A,B from BadTable)
How could I do it nicely? I was thinking about finding the set of CORRECT keys using sth like (cannot use except - running sql server 2000)
Select A,B
from table1
not exists ( select A,B from bad table)
and then inner join that with the main query. What do you think?
Select table1.A, table1.B, table2.C, Table3.D
from table1 T1
left outer join table2 on table1.A = table2.A
left outer join tabl3 on table1.B = table3.B
where not exists (select 1 from badTable where A = T1.A and B = T1.B)
would be a good way
Select table1.A, table1.B, table2.C, Table3.D ,badtable.*
from table1
left join table2 on table1.A = table2.A
left join table3 on table1.B = table3.B
left join badtable on table1.a = badtable.a
and table1.b = badtable.b
where badtable.a is null
Related
I have 3 tables:
table1
inner join with table2; or:
inner join with table3
The query:
select table1.x
from table1 right outer join
table2
on table1.x = table2.x right outer join
table3
on table1.x = table3.x
but I can only see x values that are in both table2 and table3
Use left join, not right join, along with an appropriate filter condition:
select table1.x
from table1 left join
table2
on table1.x = table2.x left join
table3
on table1.x = table3.x
where table2.x is not null or table3.x is not null;
You might consider writing this using exists:
select t1.*
from table1 t1
where exists (select 1 from table2 t2 where t2.x = t1.x) or
exists (select 1 from table3 t3 where t3.x = t1.x);
That seems like a more natural way to implement your logic -- and you won't get duplicates when x is duplicated in table2 or table3.
I'm using SQL server manger.
I have 3 tables
I need a query that pulls t1 ands add an Origin Basin and a Destination Basin.
So far I have the following:
select T1.[Country (destination)], T3.AreaName
From T1
left outer join T2 on
T1.[Country (destination)] = T2.CountryName
inner join T3 on
T2.AreaID = T3.AreaID
inner join T3 on
T2.AreaID = T3.AreaID
Which returns:
Country | Area
However, I'm having trouble doing this for the second country column. I believe you use aliases. I've tried:
select (select AreaName
FROM T3
where T3.AreaID = T2.AreaID) as 'Area Imp',
(select AreaID
From T2
where T2.CountryName = T1.[Country (origin)]) as 'x',
(select AreaID
From T2
where T2.CountryName = T1.[Country (destination)]) as 'y'
FROM T1
But I can't get it to work.
This is what you need to do:
select t1.date, t1.country_destination, t1.country_origin, destination_area.AreaName as area_destination, origin_area.AreaName as area_origin
from t1 as t1 join t2 as destination on t1.country_destination = destination.countryname
join t2 as origin on t1.country_origin = origin.countryname
join t3 as destination_area on t2.areaid = destination_area.areaid
join t3 as origin_area on t2.areaid = origin_area.areaid
You will need to join with the same table twice, both for t2 and t3 so that you get the matching records for your needs.
It helps usually to put aliases that match the purpose of the join (in this case, destination and origin) when writing the query.
I think what you're trying to do is something like this:
select T1.*, T3dest.AreaName, T3orig.AreaName
From
T1
inner join
T2 T2dest on
T1.[Country (destination)] = T2dest.CountryName
inner join
T3 T3dest on
T2dest.AreaID = T3dest.AreaID
inner join
T2 T2orig on
T1.[Country (origin)] = T2orig.CountryName
inner join
T3 T3orig on
T2orig.AreaID = T3orig.AreaID
Note that I've switched to inner joins throughout, at the moment. If you do want left join semantics, you either need to use those for all of the joins to the T2 and T3 tables or you need to change the join order (so that the relevant T3 joins to the T2 tables occur before the attempted join with T1). It's not clear from the sample data if that's required, however.
Try this, You would still want to join on area id's
select T1.Date,T1.[Country (destination)], null [Country (origin)], T3.AreaName [AreaName(Destination)], null [AreaName(Origin)]
From T1
left outer join T2 on
T1.[Country (destination)] = T2.CountryName
inner join T3 on
T2.AreaID = T3.AreaID
union all
select T1.Date,null [Country (destination)], t1.[Country (origin)], Null [AreaName(Destination)], t3. [AreaName(Origin)]
From T1
left outer join T2 on
T1.[Country (Origin)] = T2.CountryName
inner join T3 on
T2.AreaID = T3.AreaID
So, I've been trying to do following outer joins:
SELECT * FROM table1
LEFT OUTER JOIN table2
ON table1.a = table2.a
AND table1.b = table2.b
LEFT OUTER JOIN table3
ON table1.a = table3.a
AND table1.b = table3.c
I've tested and could do it with no problems. However, the software I'm using uses the older syntax for left joins. And so I wrote it like this:
SELECT * FROM table1, table2, table3
WHERE table1.a = table2.a (+)
AND table1.b = table2.b (+)
AND table1.c = table3.a (+)
AND table2.c = table3.b (+)
Obviously, I get the ORA-01417: a table may be outer joined to at most one other table error. Any way to workaround this issue?
table1.c is not present in any table2 columns, so I'm forced to use the table1.c = table3.b clause.
I've got 3 tables that I want to join and filter on some conditions.
I've first wrote this query:
select * from table1 t1
left join (select * from table2 where table2.fieldX=...) t2
on t1.id_12=t2.id_12
left join table3
on t2.id_23=t3.id_23
where t1.fieldY=...
Then I wanted to make it looks like more canonical by rewritting it like that:
select * from table1 t1
left join table2 t2
on t1.id_12=t2.id_12
left join table3
on t2.id_23=t3.id_23
where table2.fieldX=...
and t1.fieldY=...
But it does not give the same result.
I dont't understand why...
Do you?
Thanks in advance.
When you put table2.fieldX=... in the where clause you eliminate all rows from table1 that do not have a corresponding row in table2. Effectively you are changing the left join into an inner join.
Instead, you can apply the table2 filter in the join itself:
SELECT
*
FROM
Table1 t1
LEFT JOIN Table2 t2 ON t1.id_12 = t2.id_12 AND t2.fieldX = ...
LEFT JOIN Table3 t3 ON t2.id_23 = t3.id_23
WHERE
t1.fieldY = ...
Did you add the inner select where on the second query?
SELECT *
FROM table1 t1
LEFT JOIN table2 t2
on t1.id_12=t2.id_12
LEFT JOIN table3
on t2.id_23=t3.id_23
WHERE t1.fieldY=...
and t2.fieldX=...
I am trying to JOIN the result of the first SELECT clause, between the first 2 tables (t1 and t2), with the third table (t3):
SELECT t1.*, t2.PropertyCode, t3.TBMonth
FROM Test.dbo.DailyBudgetExtract T1 , Test.dbo.DailyPropertylListExtract T2
WHERE t1.propertyid = t2.proplistid
OR t1.propertyid = t2.propertyid
INNER JOIN Test.dbo.DailyTrialBalanceExtract T3 ON t1.AccCode = t3.AcctCode
What am I doing wrong?
Here is the correct syntax for your query:
SELECT t1.*, t2.PropertyCode, t3.TBMonth
FROM Test.dbo.DailyBudgetExtract T1 JOIN
Test.dbo.DailyPropertylListExtract T2
ON t1.propertyid = t2.proplistid OR t1.propertyid = t2.propertyid INNER JOIN
Test.dbo.DailyTrialBalanceExtract T3
ON t1.AccCode = t3.AcctCode;
The where clause goes after the from clause. But you don't need a where clause, just put the condition in the on clause, where it should go for an explicit join.
This syntax might be clearer:
SELECT
t1.*,
t2.PropertyCode,
t3.TBMonth
FROM
Test.dbo.DailyBudgetExtract T1
JOIN
Test.dbo.DailyPropertylListExtract T2
ON
( t1.propertyid = t2.proplistid
OR
t1.propertyid = t2.propertyid
)
INNER JOIN
Test.dbo.DailyTrialBalanceExtract T3
ON
t1.AccCode = t3.AcctCode
;
Join are part of the projection, not selection (SQL databases make use of some relational algebra). Even if it happens to be executable in some DB (which I donĀ“t think it is) you should avoid it.
You should use EXISTS and NOT EXISTS (which are knows as semi joins) instead.
The query below is a "transliteration" of your query. If it does not return what you want let me know.
SELECT t1.*,
t2.PropertyCode,
t3.TBMonth
FROM Test.dbo.DailyBudgetExtract T1
JOIN Test.dbo.DailyPropertylListExtract T2
ON (t1.propertyid = t2.proplistid OR t1.propertyid = t2.propertyid)
JOIN Test.dbo.DailyTrialBalanceExtract T3
ON t1.AccCode = t3.AcctCode
If you happen to not need the "t3.TBMonth" field
SELECT t1.*,
t2.PropertyCode
FROM Test.dbo.DailyBudgetExtract T1
JOIN Test.dbo.DailyPropertylListExtract T2
ON (t1.propertyid = t2.proplistid OR t1.propertyid = t2.propertyid)
WHERE EXISTS(SELECT 1 FROM Test.dbo.DailyTrialBalanceExtract T3 WHERE t1.AccCode = t3.AcctCode)
TIPS and NOTES:
At least in SQL Server there is no diff between "INNER JOIN" and "JOIN", so pick one and stay with it;
Using "... FROM table1 t1, table t2" is the same as CROSS JOIN;
Avoid having to do JOIN conditions with OR (you do a JOIN [aka INNER JOIN] with your "... FROM table1 t1, table t2" plus "t1.propertyid = t2.proplistid OR t1.propertyid = t2.propertyid") they slow down the query a lot;