'WHERE' syntax equivalent of LEFT OUTER JOIN in PostgreSQL - sql

I know there is a WHERE representation of LEFT JOIN in Oracle that has syntax like:
FROM t1, t2
WHERE t1.id = t2.id(+)
instead of:
FROM t1 LEFT JOIN t2
ON t1.id = t2.id
Is there anything similar in PostgreSQL? I searched for documentation, but failed to find such feature.

There is no such operator in Postgres (or standard SQL).
The only way to write an outer join in Postgres is to use an ANSI explicit JOIN syntax:
select *
from table t1
left join table t2 on t1.id = t2.id;
(or it might be the other way round - it has been ages since I last used the Oracle (+) operator)
More details in the manual: http://www.postgresql.org/docs/current/static/queries-table-expressions.html#QUERIES-FROM
You shouldn't be using the (+) operator in Oracle in the first place. Oracle has supported ANSI joins since 9i and Oracle recommends stop using the (+) operator (the above statement will work just fine in Oracle as well)

Related

Can in line views in oracle sql contain "not in" clause in the query?

For example
select *
from t1
inner join (select * from t2 where t2.id not in (select ID from t2 where city="Paris"))
I tried searching Google. There a lot of examples but none of them uses not in. Plus there are no restrictions specified for an in line view.
Oracle calls subqueries in the FROM clause "inline views".
These are generic SELECT queries. They can contain NOT IN with subqueries. The problem with your query is a lack of ON clause and the use of double quotes for a string constant:
select *
from t1 inner join
(select *
from t2
where t2.id not in (select ID from t2 where city = 'Paris')
---------------------------------------------------------^ single quotes
) t2
on t1.? = t2.?
-----^ on clause
Note: I would discourage you from using NOT IN with subqueries, because they do not work as expected if any returned values are NULL. (If that is the case, then no rows are returned.)
I advise using NOT EXISTS instead.

what operation does "select from table1, table2 " imply? [duplicate]

This question already has answers here:
Select from Table1, Table2
(3 answers)
Closed 4 years ago.
I know different joins, but I wanted to know which of them is being used when we run queries like this:
select * from table1 t1, table2 t2
is it full outer join or natural join for example?
Also does it have a unique meaning among different databases or all do the same?
UPDATE: what if we add where clause ? will it be always inner join?
The comma in the from clause -- by itself -- is equivalent to cross join in almost all databases. So:
from table1 t1, table2 t2
is functionally equivalent to:
from table1 t1 cross join table2 t2
They are not exactly equivalent, because the scoping rules within the from clause are slightly different. So:
from table1 t1, table2 t2 join
table3 t3
on t1.x = t3.x
generates an error, whereas the equivalent query with cross join works.
In general, conditions in the WHERE clause will always result in the INNER JOIN. However, some databases have extended the syntax to support outer joins in the WHERE clause.
I can think of one exception where the comma does not mean CROSS JOIN. Google's BigQuery originally used the comma for UNION ALL. However, that is only in Legacy SQL and they have removed that in Standard SQL.
Commas in the FROM clause have been out of fashion since the 1900s. They are the "original" form of joining tables in SQL, but explicit JOIN syntax is much better.
To me, they also mean someone who learned SQL decades ago and refused to learn about outer joins, or someone who has learned SQL from ancient materials -- and doesn't know a lot of other things that SQL does.
demo: db<>fiddle
This is a CROSS JOIN (cartesian product). So both of the following queries are equal
SELECT * FROM table1, table2 -- implicit CROSS JOIN
SELECT * FROM table1 CROSS JOIN table1 -- explicit CROSS JOIN
concerning UPDATE
A WHERE clause makes the general CROSS JOIN to an INNER JOIN. An INNER JOIN can be got by three ways:
SELECT * FROM table1, table2 WHERE table1.id = table2.id -- implicit CROSS JOIN notation
SELECT * FROM table1 CROSS JOIN table2 WHERE table1.id = table2.id -- really unusual!: explicit CROSS JOIN notation
SELECT * FROM table1 INNER JOIN table2 ON (table1.id = table2.id) -- explicit INNER JOIN NOTATION
Further reading (wikipedia)

(+) sign in sql code

Can anyone explain what the (+) sign means in the below code.
SELECT DISTINCT ph.po_nbr, rd.id
FROM po_head a, rtable_dtl e
WHERE a.org = e.org (+)
AND a.menu_nbr = e.menu_nbr(+)
AND UPPER(a.user_id) = UPPER(e.user_id(+))
An example:
SELECT
t0.foo, t1.bar
FROM
FIRST_TABLE t0, SECOND_TABLE t1
WHERE
t0.ID (+) = t1.ID;
This is an Oracle-specific notation for an outer join. It means that it will include all rows from t1, and use NULLS in the t0 columns if there is no corresponding row in t0.
In standard SQL one would write:
SELECT t0.foo, t1.bar
FROM FIRST_TABLE t0
RIGHT OUTER JOIN SECOND_TABLE t1;
Oracle recommends not to use those joins anymore if your version supports ANSI joins (LEFT/RIGHT JOIN):
Oracle recommends that you use the FROM clause OUTER JOIN syntax rather than the Oracle join operator. Outer join queries that use the Oracle join operator (+) are subject to the following rules and restrictions […]

Postgres/netezza multiple join from multiple tables

Hi I have a problem when migrating from ORACLE to Netezza, netezza seems to have problem if multiple tables is declared before using JOIN`s. How could I write this join differently ?
INSERT INTO...
SELECT...
FROM table1 t1, table2 t2 //here seems to be the problem as postgres dont allow to put two tables in FROM clause if there are JOIN`s involved
JOIN talbe3 t3 ON t2.column = t3.column
JOIN table4 t4 ON t2.column = t4.column
LEFT OUTER JOIN table5 t5 ON (t4.column=t5.column AND t4.column=t2.column AND t4.column=t3.column)
WHERE....;
You simply should not mix old-style (implicit) and new-style (explicit) joins. In fact, a simple rule is simply to avoid commas in the from clause.
I imagine the problem that you have is a scoping problem for the table aliases. I know this happens in MySQL. But, because I never use commas in from clauses, I am not aware of how this affects other databases. I think the part of the from clause after the comma is parsed as a unit, and the aliases defined before are not known during this parsing stage.
In any case, whatever the problem, the simple solution is to replace the comma with CROSS JOIN:
INSERT INTO...
SELECT...
FROM table1 t1 CROSS JOIN table2 t2 //here seems to be the problem as postgres dont allow to put two tables in FROM clause if there are JOIN`s involved
JOIN table3 t3 ON t2.column = t3.column
JOIN table4 t4 ON t2.column = t4.column
LEFT OUTER JOIN table5 t5 ON (t4.column=t5.column AND t4.column=t2.column AND t4.column=t3.column)
WHERE....;
This should work in all the databases you mention -- and more.

SQL ANSI joins and the order of tables in it

The following query is automatically translated from the "old" syntax to ANSI syntax and gives an error:
select *
from ods_trf_pnb_stuf_lijst_adrsrt2 lst
join ods_stg_pnb_stuf_pers_adr pas
on (pas.soort_adres = lst.soort_adres)
right outer join ods_stg_pnb_stuf_pers_nat nat
on (prs.id = nat.prs_id) <<<prs.id invalid identifier
join ods_stg_pnb_stuf_adr adr
on (adr.id = pas.adr_id)
join ods_stg_pnb_stuf_np prs
on (prs.id = pas.prs_id)
I guess this is because table prs is referenced before it has been declared. Moving the prs join up in the query solves the problem:
select *
from ods_trf_pnb_stuf_lijst_adrsrt2 lst
join ods_stg_pnb_stuf_pers_adr pas
on (pas.soort_adres = lst.soort_adres)
join ods_stg_pnb_stuf_np prs <<< this first
on (prs.id = pas.prs_id)
right outer join ods_stg_pnb_stuf_pers_nat nat
on (prs.id = nat.prs_id) <<< now prs.id is known
join ods_stg_pnb_stuf_adr adr
on (adr.id = pas.adr_id)
where lst.persoonssoort = 'PERSOON'
and pas.einddatumrelatie is null
Is there a way to write this query so that the order is less restrictive, still using the ANSI syntax?
If the broken query was generated by a tool from the old non-ANSI syntax, the tools is generated broken code. However, using ANSI-style joins should yield the same result regardless of the order of tables in the from clause. That is
select *
from t1
join t2 on t2.id = t1.id
left join t3 on t3.id = t1.id
will give you the same results (albeit a different ordering of columns in the result set) as
select *
from t1
left join t3 on t3.id = t1.id
join t2 on t2.id = t1.id
Note that the from clause can't be reordered in such a way as to break the dependencies implied by the join criteria. However, you may also, restate/refactor the from clause so as to express the query in a different way that will yield the same result set. For instance, the above query is equivalent to
select *
from t3
right join t1 on t1.id = t3.id
join t2 on t2.id = t1.id
You simply cannot reference a table unless it has been in the join list earlier. That is normal and expected behavior. Why is this a problem?
A normal ("INNER") JOIN
SELECT ...
FROM a
JOIN b ON (a.x = b.y)
is equivalent to a SELECT with two tables and an appropiate WHERE clause
SELECT ...
FROM a, b
WHERE a.x = b.y
For left/right/outer joins, you are still handicapped by "the asymmetric" join syntax.
I think the original SQL code should be something looks like this,
select *
from ods_trf_pnb_stuf_lijst_adrsrt2 lst
, ods_stg_pnb_stuf_pers_adr pas
, ods_stg_pnb_stuf_pers_nat nat
, ods_stg_pnb_stuf_adr adr
, ods_stg_pnb_stuf_np prs
where
pas.soort_adres = lst.soort_adres
and prs.id(+) = nat.prs_id
and adr.id = pas.adr_id
and prs.id = pas.prs_id
and lst.persoonssoort = 'PERSOON'
and pas.einddatumrelatie is null
ods_stg_pnb_stuf_np prs is at the end of from clause which is valid in Oracle proprietary joins,
But when convert this to ANSI SQL syntax, table prs should be joined first before it was referenced. This is a common mistake that people made when convert Oracle proprietary joins to ANSI SQL syntax.
There are some other issues when convert Oracle proprietary joins to ANSI SQL syntax:
additional join condition was missing.
condition in where clause was broken after moving some conditions to join clause.
If your colleague need to rewrite Oracle proprietary joins to ANSI SQL syntax, demos(both in java and C#) listed in this article should be helpful.