Odd behavior with query using DBLink - sql

This is will be difficult to reproduce.
A query with this pattern
SELECT *
FROM table1 t1
LEFT
JOIN table2#myLink t2
ON t1.key_field = t2.key_field
LEFT
JOIN (SELECT a.*,
3 dummyField
FROM table3#myLink a
) t3
ON T1.key_key = t3.key_Field
AND t3.dummyfield =
( SELECT 3
FROM dual
);
Fails with this error
ORA-01799: a column may not be outer-joined to a subquery
01799. 00000 - "a column may not be outer-joined to a subquery"
*Cause: <expression>(+) <relop> (<subquery>) is not allowed.
*Action: Either remove the (+) or make a view out of the subquery.
In V6 and before, the (+) was just ignored in this case.
Here's where it gets weird, this pattern works just fine:
SELECT *
FROM table1 t1
LEFT
JOIN (SELECT * FROM table2#myLink) t2 -- Note trivial subquery wrapper
ON t1.key_field = t2.key_field
LEFT
JOIN (SELECT a.*,
3 dummyField
FROM table3#myLink a
) t3
ON T1.key_key = t3.key_Field
AND t3.dummyfield =
( SELECT 3
FROM dual
);
Any thoughts? What on earth is happening here?
Also, I have these tables in the same schema in a different environment and the first query runs without error without the db links.

the problem arises on the last condition where the left side operand is column whether right side operand is subquery for the outer joined query :
AND t3.dummyfield = ( SELECT 3 FROM dual );
if you change this part as :
WHERE t3.dummyfield = ( SELECT 3 FROM dual );
your problem will be resolved.
your working query will be:
SELECT *
FROM table1 t1
LEFT JOIN table2#myLink t2
ON t1.key_field = t2.key_field
LEFT JOIN
(SELECT a.*,3 dummyField
FROM table3#myLink a) t3
ON T1.key_key = t3.key_Field
WHERE t3.dummyfield = ( SELECT 3
FROM dual
);
PS: please note that both of your queries has syntax error on the second LEFT JOIN ON operand.
PS: please note that your second query does not work as well with the JOIN (SELECT * FROM table2#myLink) t2

The following is taken from Oracle Support Doc ID 2258768.1
We do not support outer joining a column to a subquery and hence ORA-1799 is expected behavior.
However ORA-1799 incorrectly gets avoided due to query transformation when query refers local object.

Related

How join a table and selectable stored procedure filtering some rows?

In Firebird 2.5.9, I am trying to join a stored procedure in a query:
SELECT *
FROM T1
LEFT JOIN STORED_PROC(T1.STARTDATE) ON 1=1
WHERE T1.STARTDATE IS NOT NULL
This stored procedure has a parameter, a data, that it is declared as not null.
When I execute it, I get the following error:
insert failed because a column definition includes validation
constraints.Validation error for variable MINDATE, value "*** null
***".
I seems that it is receiving a null value, even the WHERE should excloude the null values. I thought that LEFT JOIN forces to evaluate first the table. Does it mean that the LEFT JOIN includes all records, do the join, and finally filter using the WHERE?
If I do:
SELECT *
FROM T1
LEFT JOIN STORED_PROC('2021-1-1') ON 1=1
WHERE T1.STARTDATE IS NOT NULL
it does not return error, but obviously it is not correct. It is just to confirm that the error is in the passed date.
Finally, if I do:
SELECT * FROM
(SELECT * FROM T1 WHERE T1.STARTDATE IS NOT NULL) AS A1
LEFT JOIN STORED_PROC(A1.STARTDATE) ON 1=1
then it works fine, but I would like to know because the first version does not work.
I think you can just filter the values first and then can join it -
SELECT *
FROM (SELECT *
FROM T1
WHERE T1.STARTDATE IS NOT NULL) TEMP
LEFT JOIN STORED_PROC(TEMP.STARTDATE) ON 1=1

H2 does not allow to execute select with join inside set

I want to fill all columns in one table basing on columns from select with left join from two others:
update TAB1 as P
set P.COL1 = (
select CODE from (
select * from TAB2 as A left outer join TAB3 as T on A.TAGID = T.ID
) as O
where P.ACTID = O.ACTID
);
It works properly on Oracle, but when i want to execute it on h2 I got this error:
Duplicate column name "ID"; SQL statement
I dont know where is a problem. I could'nt find any solution for that.
Thx for the answers
This statement is your problem:
(select * from TAB2 as A left outer join TAB3 as T on A.TAGID = T.ID)
Presumably, you have an ID in both tables, so the SELECT * returns two columns named ID. I'm surprised this works in Oracle -- but perhaps Oracle optimizes the code because the IDs are not needed.
Just return the value you want:
(select ?.CODE from TAB2 as A left outer join TAB3 as T on A.TAGID = T.ID)
The question mark is either A or T, depending on which table the value comes from.

Standard SQL: LEFT JOIN by two conditions using BETWEEN

I have the following query in BigQuery:
#Standard SQL
SELECT *
FROM `Table_1`
LEFT JOIN `Table_2` ON (timestamp BETWEEN TimeStampStart AND TimeStampEnd)
But I get the following Error:
Error: LEFT OUTER JOIN cannot be used without a condition that is an equality of fields from both sides of the join.
If I use JOIN instead of LEFT JOIN, it works, but I want to keep all the rows from Table_1 (so also the ones which aren't matched to Table_2)
How to achieve this?
This is absolutely stupid... but the same query will work if you add a condition that matches a column from table1 with a column from table2:
WITH Table_1 AS (
SELECT CAST('2018-08-15' AS DATE) AS Timestamp, 'Foo' AS Foo
UNION ALL
SELECT CAST('2018-09-15' AS DATE), 'Foo'
), Table_2 AS (
SELECT CAST('2018-08-14' AS DATE) AS TimeStampStart, CAST('2018-08-16' AS DATE) AS TimeStampEnd, 'Foo' AS Bar
)
SELECT *
FROM Table_1
LEFT JOIN Table_2 ON Table_1.Foo = Table_2.Bar AND Table_1.Timestamp BETWEEN Table_2.TimeStampStart AND Table_2.TimeStampEnd
See if you have additional matching criteria that you can use (like another column that links table1 and table2 on equality).
A LEFT JOIN is always equivalent to the UNION of :
the INNER JOIN between the same two arguments on the same join predicate, and
the set of rows from the first argument for which no matching row is found (and properly extended with null values for all columns retained from the second argument)
That latter portion can be written as
SELECT T1.*, null as T2_C1, null as T2_C2, ...
FROM T1
WHERE NOT EXISTS (SELECT * FROM T2 WHERE )
So if you spell out the UNION you should be able to get there.
Interesting. This works for me in standard SQL:
select *
from (select 1 as x) a left join
(select 2 as a, 3 as b) b
on a.x between b.a and b.b
I suspect you are using legacy SQL. Such switch to standard SQL. (And drop the parentheses after the between.)
The problem is:
#(Standard SQL)#
This doesn't do anything. Use:
#StandardSQL
Hi as per the documentation, "(" has a special meaning, so please try without the brackets.
SELECT * FROM Table_1
LEFT JOIN Table_2 ON Table_1.timestamp >= Table_2.TimeStampStart AND Table_1.timestamp <= Table_2.TimeStampEnd
Documentation here

I cannot get this LEFT JOIN to work (I don't understand joins)

These queries both get results:
SELECT * FROM Table1 WHERE Criteria = '5'
SELECT * FROM Table1 WHERE Criteria = '3'
This query gets results:
SELECT *
FROM Table1 p, Table2 m
WHERE p.UID = m.ID
AND Criteria = '5'
This query does not:
SELECT *
FROM Table1 p, Table2 m
WHERE p.UID = m.ID
AND Criteria = '3'
I am trying to convert these to a proper join which returns results even if there are no records in the right table.
I have tried the following
SELECT *
FROM Table1 p LEFT JOIN Table2 m ON p.UID = m.ID
WHERE p.Criteria = '3'
AND m.OtherCriteria = 'Moron'
--0 results
My limited understanding was that LEFT join is what I needed. I want data from the left table even if there is no data in the right table that matches. Since this didn't work I also tried right join, left outer join, right outer join and full join. None returned results.
What am I missing?
This is too long for a comment. Your query:
SELECT *
FROM Table1 p LEFT JOIN
Table2 m
ON p.UID = m.ID AND p.Criteria = '3';
Should be returning a row for all rows in table1. If there is no match, then the values will be NULL for table2. This is easily demonstrated: Here is a MySQL example on SQL Fiddle. Because this is standard behavior, it should work on almost any database.
Note that this query is quite different from this one:
SELECT *
FROM Table1 p LEFT JOIN
Table2 m
ON p.UID = m.ID
WHERE p.Criteria = '3';
This query returns no rows, because no rows match the WHERE clause. The filtering happens (conceptually) after the LEFT JOIN.
I changed the code in the SQL Fiddle slightly, so that query is:
select *
from (select 5 as criteria, 1 as id union all
select 6, 1 union all
select 7, 2
) table1 left join
(select 1 as id, 'x' as x
) table2
on table1.id = table2.id and criteria = 3;
As a note: you should always use explicit join syntax. Simple rule: Never use commas in the FROM clause.
If your database is returning no rows, then it is behaving in a non-standard manner or your interface has decided to filter the rows for some reason.

Outer Join with Where returning Nulls

Hi I have 2 tables. I want to list
all records in table1 which are present in
table2
all records in table2 which are not present in table1 with a where condition
Null rows will be returned by table1 in second condition but I am unable to get the query working correctly. It is only returning null rows
SELECT
A.CLMSRNO,A.CLMPLANO,A.GENCURRCODE,A.CLMNETLOSSAMT,
A.CLMLOSSAMT,A.CLMCLAIMPRCLLOSSSHARE
FROM
PAKRE.CLMCLMENTRY A
RIGHT OUTER JOIN (
SELECT
B.CLMSRNO,B.UWADVICETYPE,B.UWADVICENO,B.UWADVPREMCURRCODE,
B.GENSUBBUSICLASS,B.UWADVICENET,B.UWADVICEKIND,B.UWADVYEAR,
B.UWADVQTR,B.ISMANUAL,B.UWCLMNOREFNO
FROM
PAKRE.UWADVICE B
WHERE
B.ISMANUAL=1
) r
ON a.CLMSRNO=r.CLMSRNO
ORDER BY
A.CLMSRNO DESC;
Which OS are you using ?
Table aliases are case sensistive on some platforms, which is why your join condition ON a.CLMSRNO=r.CLMSRNO fails.
Try with A.CLMSRNO=r.CLMSRNO and see if that works
I'm not understanding your first attempt, but here's basically what you need, I think:
SELECT *
FROM TABLE1
INNER JOIN TABLE2
ON joincondition
UNION ALL
SELECT *
FROM TABLE2
LEFT JOIN TABLE1
ON joincondition
AND TABLE1.wherecondition
WHERE TABLE1.somejoincolumn IS NULL
I think you may want to remove the subquery and put its columns into the main query e.g.
SELECT A.CLMSRNO, A.CLMPLANO, A.GENCURRCODE, A.CLMNETLOSSAMT,
A.CLMLOSSAMT, A.CLMCLAIMPRCLLOSSSHARE,
B.CLMSRNO, B.UWADVICETYPE, B.UWADVICENO, B.UWADVPREMCURRCODE,
B.GENSUBBUSICLASS, B.UWADVICENET, B.UWADVICEKIND, B.UWADVYEAR,
B.UWADVQTR, B.ISMANUAL, B.UWCLMNOREFNO
FROM PAKRE.CLMCLMENTRY A
RIGHT OUTER JOIN PAKRE.UWADVICE B
ON A.CLMSRNO = B.CLMSRNO
WHERE B.ISMANUAL = 1
ORDER
BY A.CLMSRNO DESC;