I have a SQL query similar as below:
select *
from TableA
left outer join TableB on...
left outer join TableC on...
...
left outer join TableN on...
where
TableA.id in (subquery);
This query takes a long time to execute and I checked the execution plan of it and and found out that it did the joins first and then the where. However, the joins takes long time to finish. I run the same query against Oracle and Oracle did the optimization so that it does the 'where' part together with the joins and so that the time is much short.
My question is: how can I optimize the SQL query so that Postgres can do the 'where' part first?
PS: I cannot add the subquery into the 'from' part using an inner join because I am using Hibernate and it doesn't support subquery in 'from' part.
As already discussed widely in the comments to your post there is a possibility that the "FROM (subquery) tblalias" approach might still work, so here it is as pseudocode again:
select * from (
select * from TableA where id in (subquery)
) tblA
left outer join TableB on...
left outer join TableC on...
...
left outer join TableN on...
But - who knows for definite, as pseudocode cannot be tested ...
Related
When I write an exist query in ORACLE JOIN syntax like this, it works fine as expected.
Select * from TableA
where not exists (Select 1 from TableB where TableB.Id = TableA.TableBForeignKeyId)
When i write it as ANSI JOIN syntax, it doesn't work.
Select * from TableA
where not exists (Select 1
from (TableA
INNER JOIN TableB
on TableA.TableBForeignKeyId = TableB.Id))
On the ANSI JOIN version, TableA behave not like the upper querys TableA, because of that, the complete query returns no rows.
Not: There is only one row on TableA that has no reference on TableB.
This query should return one row of TableA.
Why ANSI JOIN behave like this?
The syntax you have written in the first query is good: i.e.
Select * from TableA
where not exists (Select 1 from TableB where TableB.Id = TableA.TableBForeignKeyId)
In the second query, TableA of the inner query will not refer to the outer TableA and hence you are not getting the desired result.
Why you are not happy with the first query?
If you are looking for some other way of writing the query then you can use the following query:
Select * from TableA
where TableA.TableBForeignKeyId not in (Select TableB.Id
from TableB )
Cheers!!
The two queries are not similar at all.
The first is a correlated subquery. The WHERE condition refers to the outer query.
The second is an uncorrelated subquery. There is no connection to the outer query. In this case, the subquery returns a single value, independent of the outer query. If it returns no rows, then the overall query returns no rows. If it returns one or more rows, then the overall query returns multiple rows.
Both are valid, correct syntax. You should use the one you want, which would normally be the correlated subquery.
I need to select all data from 2 tables in an sql database.
I searched the site and dried numerous ways but no sucess.
One table has no data but the other is full of it.
If i select each one individually i get good results, but if i use for instance:
select * from relatorio cross join temp
or
select * from relatorio r,temp t
or even:
select t.*, r.* from temp t inner join relatorio r on 1=1
The join works, but none of them shows data.
Can anyone help?
Thanks in advance.
All three select statements in the questions are cross joins.
A cross joins returns data only if both tables have at least one row.
It returns a cartesian product of both tables, meaning that every row in one table will be joined to every row in the other table.
One table has no data but the other is full of it.
Since one of your tables is empty, it will return no results at all. You can think about it as multipling by 0.
Now you have two options: one is to use a full join and the other one is to use left join, in this case both will return the same results, since one table is empty:
select *
from relatorio
left join temp on <join condition> -- assuming temp is the empty table
or
select *
from relatorio
full join temp on <join condition> -- in this case, it doesn't matter what table is empty
If you want to return all matched and umatched rows, use Full Outer Join.The FULL OUTER JOIN keyword returns all rows from the left table (table1) and from the right table (table2).
The FULL OUTER JOIN keyword combines the result of both LEFT and RIGHT joins.
In SQL the FULL OUTER JOIN combines the results of both left and right outer joins and returns all (matched or unmatched) rows from the tables on both sides of the join clause.
SQL FULL OUTER JOIN Syntax:
SELECT column_name(s)
FROM table1
FULL OUTER JOIN table2
ON table1.column_name=table2.column_name;
The SQL CROSS JOIN produces a result set which is the number of rows in the first table multiplied by the number of rows in the second table if no WHERE clause is used along with CROSS JOIN. This kind of result is called as Cartesian Product.
If WHERE clause is used with CROSS JOIN, it functions like an INNER JOIN.
An alternative way of achieving the same result is to use column names separated by commas after SELECT and mentioning the table names involved, after a FROM clause.
CROSS JOIN SYNTAX
SELECT *
FROM table1
CROSS JOIN table2;
Which approach should I use ?
This
Select * from table1,table2 where table1.id=table2.id;
or
Select * from table1 inner join table2 on table1.id=table2.id;
Note : Id is foriegn Key .
In most modern RMDBS both would yield the same execution plan but
the second one is the reccommended form since it makes clear what are the join conditions right after you declare said join
If your query gets big as they do, the second style is usually regarded as easier to read and comprehend as the JOIN and the WHERE parts of the query are separated.
Select * from table1
INNER JOIN table2 on table1.id=table2.id
INNER JOIN table3 on table1.id=table3.id
WHERE table2.something = 1
Indeed both styles should have the same execution pan under the hood.
How does one implement SQL joins without using the JOIN keyword?
This is not really necessary, but I thought that by doing this I could better understand what joins actually do.
The basic INNER JOIN is easy to implement.
The following:
SELECT L.XCol, R.YCol
FROM LeftTable AS L
INNER JOIN RightTable AS R
ON L.IDCol=R.IDCol;
is equivalent to:
SELECT L.XCol, R.YCol
FROM LeftTable AS L, RightTable AS R
WHERE L.IDCol=R.IDCol;
In order to extend this to a LEFT/RIGHT/FULL OUTER JOIN, you only need to UNION the rows with no match, along with NULL in the correct columns, to the previous INNER JOIN.
For a LEFT OUTER JOIN, add:
UNION ALL
SELECT L.XCol, NULL /* cast the NULL as needed */
FROM LeftTable AS L
WHERE NOT EXISTS (
SELECT * FROM RightTable AS R
WHERE L.IDCol=R.IDCol)
For a RIGHT OUTER JOIN, add:
UNION ALL
SELECT NULL, R.YCol /* cast the NULL as needed */
FROM RightTable AS R
WHERE NOT EXISTS (
SELECT * FROM LeftTable AS L
WHERE L.IDCol=R.IDCol)
For a FULL OUTER JOIN, add both of the above.
There is an older deprecated SQL syntax that allows you to join without using the JOIN keyword.. but I personally find it more confusing than any permutation of the JOIN operator I've ever seen. Here's an example:
SELECT A.CustomerName, B.Address1, B.City, B.State, B.Zip
FROM dbo.Customers A, dbo.Addresses B
WHERE A.CustomerId = B.CustomerId
In the older way of doing it, you join by separating the tables with a comma and specifying the JOIN conditions in the WHERE clause. Personally, I would prefer the JOIN syntax:
SELECT A.CustomerName, B.Address1, B.City, B.State, B.Zip
FROM dbo.Customers A
JOIN dbo.Addresses B
ON A.CustomerId = B.CustomerId
The reason you should shy away from this old style of join is clarity and readability. When you are simply joining one table to another, it's pretty easy to figure out what's going on. When you're combining multiple types of joins across a half dozen (or more) tables, this older syntax becomes very challenging to manage.
The best way to get a handle on the JOIN operator is working with it. Here's a decent visual example of what the different JOINs do:
http://blog.codinghorror.com/a-visual-explanation-of-sql-joins/
Some more info:
https://sqlblog.org/2009/10/08/bad-habits-to-kick-using-old-style-joins
http://www.sqlservercentral.com/blogs/brian_kelley/2009/09/30/the-old-inner-join-syntax-vs-the-new-inner-join-syntax/
When SQL was an infant we didn't have "inner join" "left outer join" etc. All we did was list the tables like this:
FROM table1, table2, table3, .... tablen
Then we had a where clause that was like a novel in length, some of the conditions were for filtering the data, many of the conditions were to join tables, like this
FROM table1, table2, table2, .... tablen
WHERE table1.code = 'x' and table1.id = table3.fk and table2.name like 'a%' and table2.id = table1.fk and tablen.fk = table3.id and table2.dt >= '2014-01-01'
from this we hoped like heck we had all the tables nicely related and we crossed our fingers. The worst case scenario - which happened a lot - was that we forgot to include a table at all in the where clause. This was not nice because what we get when we do that is a "Cartesian product" (basically a multiplication of all rows by the number of rows in the table we missed).
Then came ANSI standard join syntax, and life was better. We now place the join conditions on the join - not in the where clause - and as a bonus the where clause is easier to understand.
I don't think you will find it easier to understand this ancient syntax, for example an outer join was join = bizarre(+) or maybe it was (+)bizarre = join (I try not to remember).
Try http://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins
I've come across some SQL queries in Oracle that contain '(+)' and I have no idea what that means. Can someone explain its purpose or provide some examples of its use?
Thanks
It's Oracle's synonym for OUTER JOIN.
SELECT *
FROM a, b
WHERE b.id(+) = a.id
gives same result as
SELECT *
FROM a
LEFT OUTER JOIN b
ON b.id = a.id
The + is a short cut for OUTER JOIN, depending on which side you put it on, it indicates a LEFT or RIGHT OUTER JOIN
Check the second entry in this forum post for some examples
You use this to assure that the table you're joining doesn't reduce the amount of records returned. So it's handy when you're joining to a table that may not have a record for every key you're joining on.
For example, if you were joining a Customer and Purchase table:
To list all customers and all their purchases, do an outer join (+) on the Purchase table so customers that haven't purchased anything still show up in your report.
IIRC, the + is used in older versions of Oracle to indicate an outer join in the pre-ANSI SQL join syntax. In other words:
select foo,bar
from a, b
where a.id = b.id+
is the equivalent of
select foo,bar
from a left outer join b
on a.id = b.id
NOTE: this may be backwards/slightly incorrect, as I've never used the pre-ANSI SQL syntax.