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 :(
Related
I'm new to SQL and need a push in the right direction.
I currently have a working SQL query accessing 3 tables in a database, and I need to add a JOIN using a 4th table, but the syntax escapes me. To simplify, what I have now is:
SELECT
t1_col1, t1_col2, t2_col1, t2_col2, t3_col1
FROM
table1, table2, table3
WHERE
{some conditions}
ORDER BY
t1_col1 ASC;
What I need to do is to add a LEFT OUTER JOIN selecting 2 columns from table4 and have ON t1_field1 = t4_field1, but whatever I try, I'm getting syntax errors all over the place. I don't seem to understand the correct syntax.
I tried
SELECT *
FROM table1
LEFT OUTER JOIN table2;
which has no errors, but as soon as I start SELECTing columns and adding conditions, I get stuck.
I would greatly appreciate any assistance with this.
You do not specify the join criteria. Those would be in your WHERE clause under "some conditions". So, I will make up so that I can show syntax. The syntax you show is often termed "old". It has been discouraged for 15 years or more in the SQL Server documentation. Microsoft consistently threatens to stop recognizing the syntax. But, apparently they have not followed through on that threat.
The syntax errors you are getting occur because you are mixing the old style joins (comma separated with WHERE clause) with the new style (LEFT OUTER JOIN) with ON clauses.
Your existing query should be changed to something like this. The tables are aliased because it makes it easier to read and is customary. I just made up the JOIN criteria.
SELECT t1_col1, t1_col2, t2_col1, t2_col2, t3_col1
FROM table1 t1
INNER JOIN table2 t2 ON t2.one_ID = t1.one_ID
INNER JOIN table3 t3 ON t3.two_ID = t2.two_ID
LEFT OUTER JOIN table4 t4 ON t4.three_ID = t3.three_ID
I hope that helps with "a push in the right direction."
You may also want to read this post that explains the different ways to join tables in a query. What's the difference between INNER JOIN, LEFT JOIN, RIGHT JOIN and FULL JOIN?
Also for the record the "OLD STYLE" of joining tables (NOT RECOMMENDED) would look like this (but do NOT do this - it is a horrible way to write SQL). And it does not work for left outer joins. Get familiar with using the ...JOIN...ON... syntax:
SELECT t1_col1, t1_col2, t2_col1, t2_col2, t3_col1
FROM table1 t1, table2 t2, table3 t3
LEFT OUTER JOIN table4 t4 ON t4.three_ID = t3.three_ID
WHERE
t2.one_ID = t1.one_ID
AND t3.two_ID = t2.two_ID
I am trying to grasp SQL joins more intuitively. For example, learning how a RIGHT JOIN can just be re-written as a LEFT JOIN (by flipping the order of the tables) helped me understand much better the way that the two joins work.
However, now I'm wondering if an INNER JOIN could be re-written as a LEFT JOIN with a WHERE condition- meaning that their logic could be equivalent (by "logic" I do not mean the execution plan, but the way that the intended result set would be described).
Like:
SELECT * FROM HeaderTable
INNER JOIN DetailTable
ON HeaderTable.ID = DetailTable.ParentID
Which I would read as "Show me all the records from tables HeaderTable and DetailTable that have a matching value in the HeaderTable.ID and DetailTable.ParentID fields." Being the same as:
SELECT * FROM HeaderTable
LEFT JOIN DetailTable
ON HeaderTable.ID = DetailTable.ParentID
WHERE HeaderTable.ID = DetailTable.ParentID
Which I would read as "Show me all the records from tables HeaderTable and DetailTable where the value of HeaderTable.ID is the same as the value of DetailTable.ParentID."
Will these return the same result set? I am more asking about the logic being the same as opposed to one being more efficient than the other.
If I may ask, please don't answer with any Venn diagrams as these don't seem to describe the logic of a join exactly to me.
Yes, they will return the same result. The left join without the where clause would read as show me all the records from the header table and the related items from the details table or null for the details where there are no matches.
Adding a where clause relating the ids effectively transforms the left join to an inner join by eliminating the non-matching rows that would have shown up as having null for the detail part.
In some databases, like MS SQL Server, the left join would show up as an inner join in the query execution plan.
Although you stated that you don't want Venn diagrams I can't help referring you to this question and its answers even though they are filled with (in my opinion very helpful) Venn diagrams.
Yes they would return the same result.
But then you could simply write
SELECT *
FROM HeaderTable, DetailTable
WHERE HeaderTable.ID = DetailTable.ParentID
this returns the same result as well. This is an old syntax used before the join-clauses were introduced.
On a left join if you reference the left in the where then you negate the left and turn it into regular join
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 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.