I have two select statements that I am trying to port from Oracle to Postgres:
1) (Note: this is a subselect part of a bigger select)
SELECT 'Y'
FROM CRAFT MA, CONFIG MAC, ARMS SM
WHERE MCI.MS_INVENTORY_NUMBER = SM.MS_INVENTORY_NUMBER (+)
AND MCI.AB_BASE_ID = MA.AB_BASE_ID_LAUNCH AND SM.ACT_AC_TYPE = MAC.ACT_AC_TYPE
AND SM.MAC_ID = MAC.MAC_ID AND MAC.ACT_AC_TYPE = MA.ACT_AC_TYPE
AND MAC.MAC_ID = MA.MAC_ID_PRI
2)
SELECT ASP.ASP_SPACE_NM,
SUM(MO.MO_TKR_TOTAL_OFF_SCHEDULED) AS "TOTAL_PLANNED"
FROM MISSION_OBJECTIVE MO, SPACE ASP
WHERE ASP.ASP_SPACE_NM = MO.ASP_SPACE_NM (+)
AND MO.MO_MSN_CLASS_NM = 'TOP'
GROUP BY ASP.ASP_SPACE_NM
The (+) syntax is confusing for me... I know it signifies a "join", but I am not familiar enough with SQL to understand what is equivalent to what.
SELECT 'Y'
FROM CRAFT MA
JOIN CONFIG MAC
ON MAC.ACT_AC_TYPE = MA.ACT_AC_TYPE
AND MAC.MAC_ID = MA.MAC_ID_PRI
AND MA.AB_BASE_ID_LAUNCH = MCI.AB_BASE_ID
LEFT JOIN
ARMS SM
ON SM.MS_INVENTORY_NUMBER = MCI.MS_INVENTORY_NUMBER
WHERE SM.ACT_AC_TYPE = MAC.ACT_AC_TYPE
AND SM.MAC_ID = MAC.MAC_ID AND
and
SELECT ASP.ASP_SPACE_NM,
SUM(MO.MO_TKR_TOTAL_OFF_SCHEDULED) AS "TOTAL_PLANNED"
FROM SPACE ASP
LEFT JOIN
MISSION_OBJECTIVE MO
ON MO.ASP_SPACE_NM = ASP.ASP_SPACE_NM
WHERE MO.MO_MSN_CLASS_NM = 'TOP'
GROUP BY
ASP.ASP_SPACE_NM
I left the LEFT JOIN as it was in the original query, but it's redundant here due to the WHERE condition.
You may replace it with an INNER JOIN or just drop the (+) part.
(+) was Oracle's way of expressing an outer join before "LEFT JOIN" (etc.) was added to standard SQL. Some Oracle practitioners did not immediately switch over to the standard syntax, even after it was added to the Oracle dialect of SQL.
The answer you have accepted says that you can replace "LEFT JOIN" with "INNER JOIN". I'm not convinced. But I'm confused by the reference to "MCI" in the first query.
The original programmer probably had a reason for using outer join instead of inner join. You might want to check and see whether that original reason was valid.
Related
I'm in the process of converting some MS Access queries into Transact-SQL format and have run into some problems. Is there a way to write a Join within a Join?
For example:
LEFT JOIN (TaxInfo RIGHT JOIN TaxInfoJackpot
ON TaxInfo.RefNumber = TaxInfoJackpot.RefNumber)
ON HandPay.SlipNumber = TaxInfoJackpot.SlipNumber
This is just a snapshot of a much larger query of course. But, if anyone knows if this is possible any help would be great.
Thanks in advance.
I tend to like all of my joins to be sequential and flowing in the same direction, when possible (and I try to always re-order things so it is possible). LEFT JOIN / RIGHT JOIN / ON / ON is very confusing to follow for anyone, myself included, and I've been doing this for a very long time. Access certainly doesn't do anyone any favors with the bizarre syntax it pumps out (and accepts).
I am not sure if the current syntax provides the results you expect, but can you compare to this format to see if they're the same? Hard to know for sure without sample data and desired results.
SELECT ...
FROM dbo.TaxInfoJackPot AS jp
LEFT OUTER JOIN dbo.HandPay AS hp
ON hp.SlipNumber = jp.SlipNumber
LEFT OUTER JOIN dbo.TaxInfo AS ti
ON jp.RefNumber = ti.RefNumber;
You can do this with a subquery.
LEFT JOIN (
SELECT *
FROM TaxInfo ti
RIGHT JOIN TaxInfoJackpot j ON ti.RefNumber = j.RefNumber
) tij ON HandPay.SlipNumber = tij.SlipNumber
But I'm not sure if you actually need to do it this way. I think you can do this with just normal joins
FROM HandPay h
RIGHT JOIN TaxInfoJackpot j ON h.SlipNumber = j.SlipNumber
LEFT JOIN TaxInfo ti ON j.RefNumber = ti.RefNumber;
Ok, I currently tasked with maintaining a legacy SQL Server 2005 database recently migrated to 2008 [R2] and there are some sprocs with something like the following:
SELECT
#val = c.TableVal
FROM
dbo.TaqbleA a
LEFT JOIN dbo.TableB b
ON a.TableId = b.TableId
,dbo.TableC c
WHERE
a.TableId = c.TableId
Fist off I know that the join conditions as seen with table A and B are the normal and how I'd rewrite this but I'm wondering if Table C is treated as a LEFT JOIN as it is listed after the LEFT JOIN or if it is treated as an INNER JOIN? My gut says it is treated as an INNER JOIN, but I'm not certain. Which is it?
Furthermore, I know I'm not the only one who has ever seen something like this and it would be good to have this answer immortalized in the StackExchange...
Thanks.
It is effectively an INNER JOIN or CROSS JOIN; the comma has lower precedence than the explicit JOIN, so FROM ... LEFT JOIN ... ON ..., ... means FROM (... LEFT JOIN ... ON ...), ..., with the LEFT JOIN pertaining only to the first two tables.
I have a table that can link out to several other tables depending on certain conditions. Please consider the following SQL:
DECLARE #someFlag nvarchar(1) = 'B'
select COUNT(SL_A.ID) + COUNT(SL_B.ID) + COUNT(SL_C.ID) as TotalLinks
from Customers C
left outer join SomeLookupA SL_A on
#someFlag = 'A'
AND C.SomeLookupAId = SL_A.ID
left outer join SomeLookupB SL_B on
#someFlag = 'B'
AND C.SomeLookupBId = SL_B.ID
left outer join SomeLookupC SL_C on
#someFlag = 'C'
AND C.SomeLookupCId = SL_C.ID
As you can see, as #someFlag is set to 'B' only the second left outer join will return results because of the #someFlag = '<?>' condition on each join.
Now obviously I could equally split this SQL into 3 separate statements which would run in a conditional block:
if (#someFlag = 'A')
begin
select COUNT(SL_A.ID) as TotalLinks
from Customers C
left outer join SomeLookupA SL_A on
#someFlag = 'A'
AND C.SomeLookupAId = SL_A.ID
end
else if (#someFlag = 'B')
... etc.... etc...
I personally prefer the first approach as it is more succinct.
My question is, will the SQL Server engine will optimise out the redundant left joins and will the first approach generally perform just as well as the second approach?
OP here. Thought I may as well answer my own question in case anyone else ever stumbles across this in the future.
It would appear that using conditional outer joins as I have shown above, do not perform as well as the second 'non-conditional' approach. The SQL Server engine still expends some processing time on these joins even though they can't return additional results. You can see this by constructing a query and turning on the "Include Actual Execution Plan" option as suggested above in the comments.
TL;DR; The second approach is faster.
I have this query which works fine in SQL Server, but not in Access, and I'm having trouble converting it. I've always heard that JET is missing some TSQL features, and I suppose complex joins is one of them.
SELECT C.[Position], TT.[Description] as TrainingType, T.ProgramTitle, T.ProgramSubTitle, T.ProgramCode, ET.CompletedDate
from HR_Curriculum C
LEFT JOIN HR_Trainings T ON C.TrainingID = T.TrainingID
LEFT JOIN HR_TrainingTypes TT ON T.TrainingTypeID = TT.TrainingTypeID
LEFT JOIN HR_EmployeeTrainings ET ON C.TrainingID = ET.TrainingID
AND (ET.AvantiRecID IS NULL OR ET.AvantiRecID = '637')
where ( c.[Position] = 'Customer Service Representative'
OR C.[Position] = 'All Employees')
order by [Position], Description, ProgramTitle
I tried putting the extra join clause down in the WHERE clause, but for some reason this does not yield the proper count of records.
When you have more than one JOIN in ms-access you need to wrap them with parenthesis like this:
SELECT C.[Position], TT.[Description] as TrainingType, T.ProgramTitle, T.ProgramSubTitle, T.ProgramCode, ET.CompletedDate
from (((HR_Curriculum C
LEFT JOIN HR_Trainings T ON C.TrainingID = T.TrainingID)
LEFT JOIN HR_TrainingTypes TT ON T.TrainingTypeID = TT.TrainingTypeID)
LEFT JOIN HR_EmployeeTrainings ET ON C.TrainingID = ET.TrainingID
AND (ET.AvantiRecID IS NULL OR ET.AvantiRecID = '637'))
where ( c.[Position] = 'Customer Service Representative'
OR C.[Position] = 'All Employees')
order by [Position], Description, ProgramTitle
or you will have the Missing Operator error
Check that your table alias are delacred with 'as'. Access doesn't like [tablename] [alias], instead try [tablename] as [alias]. I know the complex left joins shouldn't be a problem, but Access might be choking an the alias delcarations if it's returning some join error. I would also try quering out the restriction on the ET table, and then joining that to the larger query. I've noticed that trying to put restrictions on records involved in left or right joins will often not produce the correct records as Access will limit the set after the join.
When I create a view in SQL Server 2005 and someone later opens it in the GUI modify mode it sometimes completely rearranges my joins. Often to the point it's virtually no longer readable. If I look at it in the GUI it's changed as well from what I originally wrote. Sometimes the join lines no longer even point to a field and the join symbol has "fx". I assume it has "optimized" it for me. Is there a way to prevent this from happening? And what does "fx" mean?
Originally it was something like this:
FROM dbo.Stop
LEFT OUTER JOIN dbo.StopType ON dbo.Stop.StopTypeID = dbo.StopType.StopTypeID
LEFT OUTER JOIN dbo.CityState ON dbo.Stop.City = dbo.CityState.City AND dbo.Stop.State = dbo.CityState.State
LEFT OUTER JOIN dbo.vwDrivers ON dbo.Stop.DriverID = dbo.vwDrivers.DriverID
LEFT OUTER JOIN dbo.truck ON dbo.Truck.TruckID = dbo.Stop.TruckID
INNER JOIN dbo.vwTicketIDFirstStopLastStop ON dbo.vwTicketIDFirstStopLastStop.TicketID = dbo.stop.ticketid
LEFT OUTER JOIN dbo.Company ON dbo.Company.CompanyID = dbo.vwTicketIDFirstStopLastStop.BillToCompanyID
Now it's this.
FROM dbo.Truck RIGHT OUTER JOIN
dbo.Stop INNER JOIN
dbo.StopType ON dbo.Stop.StopTypeID = dbo.StopType.StopTypeID LEFT OUTER JOIN
dbo.CityState ON dbo.Stop.City = dbo.CityState.City AND dbo.Stop.State = dbo.CityState.State LEFT OUTER JOIN
dbo.vwDrivers ON dbo.Stop.DriverID = dbo.vwDrivers.DriverID ON dbo.Truck.TruckID = dbo.Stop.TruckID LEFT OUTER JOIN
dbo.vwTicketIDFirstStopLastStop LEFT OUTER JOIN
dbo.Company ON dbo.Company.CompanyID = dbo.vwTicketIDFirstStopLastStop.BillToCompanyID ON dbo.vwTicketIDFirstStopLastStop.TicketID = dbostop.ticketid
No you cannot. That's why you should never, ever use it.
"Fx" means that the join is not a simple column-to-column link, but involves a function (that's also why it can't point to a field, of course). It should NOT do that by itself, though,
I hate the view GUI
I use RightClick->ScriptViewAs->Alter To->New Query Editor Window
So much nicer :)
It's the result of the view GUI parsing the SQL into it's own internal DOM style format and then writing it back out - much in the same way that HTML editors take in XHTML and emit stuff differently to how you wanted it :(