SQL select returns extra result - sql

Guess there are similar questions and the answere might is easy but I cant help my self and thats why I ask you guys.
I have some Data in a DB (Centura/Gupta SQLBase 7)
no Left/Right Join possible - obviously not implemented in sqlbase sql
Here is my select
SELECT
I.IARTNR,
L.ARTNAME
FROM
INVENTUR I,
LAGER L
WHERE
L.ARTSTR = I.IARTNR
AND
I.AB = '2015-81';
returns 20 rows, not 18 as expacted.
INVENTUR rows with AB set to 2015-81 are 18 and in LAGER there are <3000 rows. What I'm trying to do is select all articles von INVENTUR and add the article name thats written in LAGER.
Whats wrong with my select ? Running this "mysterious" since 3 days.

ANSI join syntax for Outer / Inner joins was added in v8.5 onwards ( now upto v12.1 ).
Before v8.5 , you can use the native Gupta Outer / Inner join syntax e.g.
SELECT t1.col1,t2.col1,t1.col2,t2.col2
FROM t1,t2
WHERE t1.col1 = t2.col1(+)
AND t1.col2 = t2.col2(+)
The next example lists customer names and their order numbers,including customers who have made no orders:
SELECT CUSTOMER.CUSTNO,NAME
FROM CUSTOMER,ORDERS
WHERE CUSTOMER.CUSTNO = ORDERS.CUSTNO(*)
The same query using ANSI syntax in SQLBase v8.5 onmwards is:
SELECT CUSTOMER.CUSTNO,NAME
FROM CUSTOMER LEFT OUTER JOIN ORDERS ON CUSTOMER.CUSTNO = ORDERS.CUSTNO

Use explicit joins.
SELECT I.IARTNR, L.ARTNAME
FROM INVENTUR I
INNER JOIN LAGER L ON I.IARTNR = L.ARTSTR
WHERE I.AB = '2015-81';
And if needs be DISTINCT.
SELECT DISTINCT I.IARTNR, L.ARTNAME
FROM INVENTUR I
INNER JOIN LAGER L ON I.IARTNR = L.ARTSTR
WHERE I.AB = '2015-81';

Of course SQLBase has inner / outer joins !
Either Native syntax ( using (+) ) or ANSI .
Here's the syntax:
NATIVE:
SELECT t1.col1, t2.col1, t1.col2, t2.col2
FROM t1, t2
WHERE t1.col1 = t2.col1 (+) AND t1.col2 = t2.col2 (+);
ANSI:
SELECT t1.col1, t2.col1, t1.col2, t2.col2
FROM t2 RIGHT OUTER JOIN t1
ON t1.col1 = t2.col1
AND t1.col2 = t2.col2 ;
p.s. SQLBase is no 'weird' database . v12 recently released will outstrip SQLServer every time in terms of performance , footprint and overall cost of ownership. Please be more aware of your facts before broadcasting nonsense.

Related

SQL: How to use WHERE instead of OUTER JOIN

I am using an old database call Centura Gupta that doesn't have the join clauses (left join, right join, inner join, outer join). So I need to use where to replace the outer join that I need:
SELECT *
FROM table1
OUTER JOIN table2
ON table1.id_person table2.id_person;
I think that where can only replaces inner join:
SELECT *
FROM table1
WHERE table1.id_person = table2.id_person;
You could try to use subqueries instead of join
SELECT *
FROM table1 t1
WHERE id_Person IN
(
SELECT id_Person
FROM table2
)
I used this kind of implementation when I didn't know JOINs. May not be exactly right but something which can get you close:
SELECT *
FROM table1 t1, table2 t2
WHERE t1.id_Person=t2.id_Person;
I don't know about that particular database, but you might be able to use a correlated subquery to get "joined" data. This will pull all records from table1 and the related info from table2, or NULL for whatever4 and whatever5 if there's no matching id_person in table2:
SELECT t1.whatever1
, t1.whatever2
, t1.whatever3
, (SELECT whatever4 FROM table2 AS t2 WHERE t2.id_person = t1.id_person) AS whatever4
, (SELECT whatever5 FROM table2 AS t2 WHERE t2.id_person = t1.id_person) AS whatever5
FROM table1 AS t1
'Old database called Centura Gupta' ??
Maybe you actually mean OpenText Gupta SQLBase - which is by no means 'old'.
You may be running an 'old' version of SQLBase - but it is now up to v12.2 native 64bit, and outer joins are certainly supported.
You can either use the native Gupta outer joins - similar to Oracle (+) or standard ANSI outer joins.
If you want to use ANSI OUTER joins, specify 'ANSIJoinSyntax=1' in your Server side Sql.ini
Go here for more SQLBase Join syntax: Gupta SQLBase Manuals
Native Gupta Outer Join:
SELECT t1.id_person, t2.id_person
From table1 t1 , table t2
Where t1.id_person = t2.id_person(+)
ANSI Outer Join:
SELECT t1.person_id, t2.person_id
From table1 t1
Left Outer Join table2 t2 ON t1.id_person = t2.id_person
Where <what ever filter you want>
Go here for more SQLBase Join syntax: Gupta SQLBase Manuals

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)

In Oracle, in regards to syntax - how do I convert the (+) syntax to modern conventional JOIN?

Suppose I have a FROM clause like so :
FROM
apps.po_requisition_lines_all prl,
apps.po_requisition_headers_all prha,
po.po_req_distributions_all prda,
po.po_distributions_all pda,
po.po_headers_all pha
where 1=1
and prl.requisition_header_id= prha.requisition_header_id
and prl.requisition_line_id= prda.requisition_line_id
and prda.distribution_id= pda.req_distribution_id(+)
and pha.po_header_id(+)=pda.po_header_id
Then how does this type of OUTER JOIN get converted if we want to use normal JOIN syntax ? thanks !
Without seeing the schema, I find it difficult but this should set you in the right direction:
FROM apps.po_requisition_lines_all prl
INNER JOIN apps.po_requisition_headers_all prha ON prl.requisition_header_id = prha.requisition_header_id
INNER JOIN po.po_req_distributions_all prda ON prda.requisition_line_id = prl.requisition_line_id
LEFT JOIN po.po_distributions_all pda ON prda.distribution_id = pda.req_distribution_id
-- I note from the example provided that this is a right join
-- Without seeing the schema, it looks to me as though it should be left
-- As I say say, without seeing the schema, I probably shouldn't pass comment
RIGHT JOIN po.po_headers_all pha ON pha.po_header_id = pda.po_header_id;
For an INNER JOIN you can just say JOIN although I think that explicitly saying INNER aids readability. I also note the example provided has WHERE 1=1 which is redundant.
The + is old version of Outer Joins, and it differs where the + comes after equality sign or before it, But now it's recommended to use Join keywords instead of +, about the + sign if it comes:
After =:
select * from t1, t2
where t1.id=t2.id(+)
This means Left Outer Join:
select * from t1
left outer join t2 on t1.id=t2.id
Before =:
select * from t1, t2
where t1.id(+)=t2.id
This means Right Outer Join:
select * from t1
Right outer join t2 on t1.id=t2.id
Without +:
select * from t1, t2
where t1.id=t2.id
This means Inner Join:
select * from t1
join t2 on t1.id=t2.id

CE Join on columns with different names

I have seen several examples to write CE functions. BUt, I have not come across any example where a join is performed on columns with different name.
For example:
With SQL:
select T1.col1, T1.col2, T1.col3 , T2.col4, T2.col5, T2.col6
from table1 T1
inner join table2 T2
on T1.col3 = T2.col7
WITH CE functions:
table1 = CE_COLUMN_TABLE("SCHEMA"."TABLE1",["col1","col2","col3"]);
table2 = CE_COLUMN_TABLE("SCHEMA"."TABLE2",["col4","col5","col6","col7"]);
var_out = CE_JOIN(:table1,:table2,[??],[])
Can anyone please help me in completing the join statement.
Thanks
Mesh
The trick here to use a projection node. A projection will allow you to rename columns and also filter data. You could do something like:
prj_1 = CE_PROJECTION(:emp_table,["ID","FNAME", "LNAME", "AGE", "PAY" AS "SALARY"], '"PAY"' > 1000);
prj_2 = CE_PROJECTION(:address,["EMP_ID" AS "ID", "ADDR1", "ADDR2", "ZIP"]);
join_1 = CE_JOIN(:prj_1, :prj_2, ["ID"]);

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.