HQL query with left join fetch on collection - hql

I have a problem with a hql query, I use the last version on hibernate on jboss7.
So, I have table1 linked to table2 and table2 has an attribute (SET) references to table3.
Here is a small schema
TABLE1-----TABLE2(attribute: transfer manyToMany) TABLE3(attribute elements)
here is my query:
select t1 from TABLE1 t1
left join fetch t1.TABLE2 t2
left join fetch t2.transfers tf (here we have a list of T3)
How to load the elements in T3 with a left join fetch, if it's possible at all?
I try tf.elements but I receive indexOutOfBounds exception.
I tried to add the T3 in the select statement and to add a condition but I didn't find a condition on the list tf.
Thanks

Related

How to tuning is not null to range scan index in Oracle explain plan?

I m building a search query right now. I used the Oracle 19c database.
sample query:
select * from t1
inner join t2 on t2.id = t1.id and t2.name <> 'AKA'
left outer join t3 Buyer on Buyer.id = t1.id and Buyer.userId is null
left outer join t3 Seller on Seller.id = t1.id and Seller.userId = t1.userId
where rownum < 500;
This query runs super slow without indexes. It took like 14s to feed the result.
I checked the explain plan and give some indexes to the database. The query time down to 3s! Yeah. BUT,BUT,BUTBBBBBUT. It's not enough. I need it to react even faster like 1s.
I rechecked the autotrace. There still two place use full scan event I gave them the index.
The first is
INDEX t2.name
- Filter Predicates
- t2.NAME<>'AKA'
Is there a way to do <> index in Oracle? I tried build index in multiple ways. For example,
create index t2_name_idx on t2 (case when name <> 'AKA' then name end);, not work. Also the sample way like create index t2_name_idx on t2 (name); not works too.
The second is
HASH JOIN RIGHT OUTER 890639 556473 400400 2906406
Access Predicates
AND
T3.ID=T1.ID
T3.USERID=T1.USERID
TABLE ACCESS
ADDRESSES BY INDEX ROWID BATCHED 1225069 314696 384117 596570
INDEX
T3_UERID FULL SCAN 1225069 4708 4678 121216
Filter Predicates
T3.USERID IS NOT NULL
Above means that when doing left outer join t3 Seller on Seller.id = t1.id and Seller.userId = t1.userId it will check the t3.userid is not null first. The index T3_USERID is just a simple non-unique index on table T3 col T3.userid.
Any help or hint will be appreciated.

how to use full outer join writing query on multiple tables?

I have a below query
How to use full outer join for TABLE T4 for getting all records?
WHERE
(DB.T4.AUTH_REV_NO=DB.T2.AUTH_REV_NO
AND DB.T4.AUTH_NO=DB.T2.AUTH_NO)
AND (DB.T2.AUTH_CURR_IN='Y' )
AND (DB.T3.AUTH_NO=DB.T2.AUTH_NO)
AND (DB.T3.AUTH_REV_NO=DB.T2.AUTH_REV_NO )
AND (DB.T6.FNC_ID=DB.T4.FNC_ID)
AND (DB.T7.FNC_SEG_ID=DB.T6.FNC_SEG_ID)
AND (DB.T1.SCT_ID(+)=DB.T7.SCT_ID
AND DB.T1.FNC_SEG_ID(+)=DB.T7.FNC_SEG_ID)
AND (DB.T8.NDE_ID=DB.T12.NDE_ID)
AND (DB.T7.FNC_SEG_ID=DB.T8.FNC_SEG_ID)
AND (DB.T7.SCT_ID=DB.T8.SCT_ID)
AND ((DB.T12.NDE_ID=DB.T6.NDE_STRT_ID)
OR (DB.T12.NDE_ID=DB.T6.NDE_END_ID))
AND (DB.T5.FNC_ID(+)=DB.T4.FNC_ID)
AND (T13_A4.REF_ID(+)=DB.T5.REF_TONE_TYP_ID)
AND (fne.FNC_SEG_ID=DB.T8.FNC_SEG_ID)
AND (fne.NDE_ID=DB.T8.NDE_ID)
AND (fne.SCT_ID=DB.T8.SCT_ID)
AND fnode.NDE_ID=DB.T6.NDE_STRT_ID
AND tnode.NDE_ID=DB.T6.NDE_END_ID
AND (DB.T4.REF_FNC_TYP_ID=T13_A1.REF_ID)
AND (ne_port.NDE_EQP_ID=fne.NDE_EQP_ID)
AND (ne_port.NDE_EQP_PRN_ID=ne_card.NDE_EQP_ID)
AND (ne_card.NDE_EQP_PRN_ID=ne_shelf.NDE_EQP_ID)
AND (ne_shelf.NDE_EQP_PRN_ID=ne_rack.NDE_EQP_ID)
AND (eq.EQP_ID=ne_card.EQP_ID)
AND (eq.REF_EQP_CLS_ID=T13_A2.REF_ID)
AND (DB.T3.REF_AUTH_STS_ID=T13_A3.REF_ID)
AND (DB.T3.AUTH_STS_ID
IN (SELECT MAX(DB.T3.AUTH_STS_ID) FROMDB.T3
WHERE (DB.T3.AUTH_NO,DB.T3.AUTH_REV_NO)
IN
(SELECT
DB.T3.AUTH_NO,
MAX(DB.T3.AUTH_REV_NO)
FROM
DB.T3
GROUP BY
DB.T3.AUTH_NO)
GROUP BY
DB.T3.AUTH_NO))
How to use full outer join for TABLE T4 and for COLUMN FNC_TONE_LVL_QT to get all records.
Please help.
You posted a whole lot of "joins". I'm not going to rewrite it for you, but - I'd suggest you to switch to a more recent explicit JOIN syntax which makes things somewhat simpler and easier to understand as you'd separate joins from conditions. Moreover, it allows you to outer join the same table to more than just one another table, which is impossible with the old (+) Oracle's outer join operator.
Something like this
select ...
from table_1 a left join table_2 b on a.id = b.id
full outer join table_3 c on c.id = a.id
...

Parameterize the Decode Function

In a oracle i'm using a Decode Statement as below. For security reasons i don't want the code to have the hardcoded values and i plan to create a new lookup table.
Select CONCAT( Decode(A.COUNTRY_INITIAL,
'A','America',
'B','Brazil',
'F','FINLAND',
NULL),
Decode(A.ADD_VALUE,
'M','YES',
NULL))
from (
Select SUBSTR(COUNTRY_BASE, -1,1) as COUNTRY_INITIAL,
SUBSTR(IS_VALUED, -1,1) as ADD_VALUE
from TBL1
)A
Refernece Table
*******************
Clmn1 Clmn2 Clmn3
--------------------------
cntry1 A America
cntry2 B Brazil
cntry3 F Finland
Value1 M YES
Could you please let me know how i can incorporate this in the decode logic. Also fyi im using this CODE SNIPPET in a Oracle Function.
If you're going to store the lookup information in a table, you wouldn't use a DECODE. You'd join the two tables
SELECT ref.clmn3
FROM tbl1 t1
LEFT OUTER JOIN <<reference table>> ref
ON( substr(t1.country_base, -1, 1) = ref.clmn2 )
Since your DECODE has a NULL, I'm guessing that you are expecting that some rows of tbl1 will not have a matching row in the reference table so I'm guessing that you want a LEFT OUTER JOIN rather than an INNER JOIN.
If you have these details in a table you can simply use a join to get desired output.
select t1.COUNTRY_BASE,ref.Clmn3,ref1.Clmn3
frorm TBL1 t1
left outer join reftable ref
on SUBSTR(t1.COUNTRY_BASE, -1,1)=ref.Clmn2
left outer join reftable ref1
on SUBSTR(t1.IS_VALUED, -1,1)=ref.Clmn2;
If your are using separate table to store the values, you don't need decode function. You can simply join the two tables.
select a.country_base,
a.is_valued,
b.clmn3,
c.clmn3
from tbl1 a left outer join reference_table b
on (substr(a.country_base, -1, 1) = b.clmn2
and b.clmn1 like 'cntry%' --extra clause needed if there are same country and value codes
)
left outer join reference_table c
on (substr(a.is_valued, -1, 1) = c.clmn2
and c.clmn1 like 'Value%' --extra clause needed if there are same country and value codes
);

Order of columns returned in SQL query (With table join)

I am wondering what determines the order of columns returned in a SQL query.
For example, SELECT * FROM SOMETABLE;
SQ_ID |BUS_TYPE |VOIP |LOCAL_PHONE
--------|-----------|---------|-------------
SQ000001|Business |Y |N
I am guessing the attribute COLUMN_ID determines this. In the case of a table join, for example, SELECT * FROM SOMETABLE LEFT JOIN OTHERTABLE USING (SOME_COL); how is the order now determine.
The order of columns in SELECT * FROM some_table is determined by the column_id of each column, as seen in USER_TAB_COLUMNS.
The order of columns in SELECT * FROM some_table JOIN other_table is all the columns for each table starting with the leftmost table after the FROM clause. In other words, this ...
SELECT * FROM some_table JOIN other_table
... is equivalent to this ...
SELECT some_table.*, other_table.* FROM some_table JOIN other_table
Changing that inner join to LEFT JOIN or RIGHT JOIN won't change the projection.
This is, of course, theoretical. We should never use select * in production code. Explicit column declarations, with table aliases when joining, are always safer. Apart from better expression of intent, explicit projections protect our code from future changes to the tables such as adding a LOB column or a column name which creates ambiguity with a joined table's column.
You can list the order of the colums in the Select statement:
SELECT SOME_COL, SOME_OTHER_COL
FROM SOMETABLE LEFT JOIN OTHERTABLE USING (SOME_COL)
But you also speak of the ID influencing the order and of ordering in general. So I think you could also be looking for ORDER BY to order the rows:
SELECT *
FROM SOMETABLE LEFT JOIN OTHERTABLE USING (SOME_COL)
ORDER BY SOME_COL
What also comes quite handy in this case is the use of aliases. Especally when both tables have coloums with the same name:
SELECT s.some_col, o.some_col
FROM SOMETABLE s LEFT JOIN OTHERTABLE o ON(o.id = s.id)
ORDER BY o.SOME_COL
I use the ON JOIN syntax in this case, because i find this more intuive when using aliases but it should also work with USING.

Select constant value

I have 2 views:
View VIEW5_SUMA that contains SUM of prices for all items (cars), it is one row and it's constant I need to "join"
View VIEW4_SUMA_AUTA that contains SUM of all incomes for specific item (car)
SQL> SELECT * FROM VIEW5_SUMA ;
CELKOVA_TRZBA
-------------
5806
SQL> SELECT * FROM VIEW4_SUMA_AUTA ;
TRZBA_AUTA ID_AUTO
---------- ----------
360 1
... ...
I need to create another view, that will contain percents of income for every item. The problem is, I dont know how to "JOIN" that one row from VIEW5_SUMA (constant of total income) to my select so I can calculate with it.
This is what I got so far but it returns error:
CREATE VIEW VIEW6 AS
SELECT
t1.typ,
t1.specifikacia_typu,
t1.SPZ,
t2.trzba_auta/(t3.celkova_trzba/100) AS percenta
FROM AUTA t1, VIEW5_SUMA t3
JOIN VIEW4_SUMA_AUTA t2 ON t1.id_auto = t2.id_auto
;
The problem you see is due to the fact that the JOIN binds tighter than the comma so what you wrote is equivalent to
FROM AUTA t1, (VIEW5_SUMA t3 JOIN VIEW4_SUMA_AUTA t2 ON t1.id_auto = t2.id_auto)
Seeing how there is no table t1 inside the parenthesis this won't work.
That means all you have to do is to change the order so that the binding works as you want it:
CREATE VIEW VIEW6 AS
SELECT
t1.typ,
t1.specifikacia_typu,
t1.SPZ,
t2.trzba_auta/(t3.celkova_trzba/100) AS percenta
FROM AUTA t1 JOIN VIEW4_SUMA_AUTA t2 ON t1.id_auto = t2.id_auto,
VIEW5_SUMA t3
;
Alternatively you can use a CROSS JOIN which is the same thing as a comma because it results in a cartesian product or changes into an inner join if there is a where clause.
FROM AUTA t1 CROSS JOIN VIEW5_SUMA t3 JOIN VIEW4_SUMA_AUTA t2 ON (...)
FROM AUTA t1 JOIN VIEW4_SUMA_AUTA t2 ON (...) CROSS JOIN VIEW5_SUMA t3
The CROSS JOIN is a JOIN so you have the expected parenthesis ((CROSS JOIN) JOIN )
Oh I found one way just after posting my question. If I dont use JOIN at all but rather specify multiple tables in FROM and then join tables with WHERE it works.
SELECT
t1.typ,
t1.specifikacia_typu,
t1.SPZ,
t2.trzba_auta/(t3.celkova_trzba/100) AS percenta
FROM AUTA t1, VIEW4_SUMA_AUTA t2, VIEW5_SUMA t3
WHERE
t1.id_auto = t2.id_auto
;
But I'm still curious if there's way to do this with JOIN.
'Returns error' is not helpful in diagnosing the problem. I'd guess it says that t1.id_auto is an invalid identifier.
Mixing the old join syntax (multiple comma-separated tables in the from clause and the join condition in the where clause) and the 'new' syntax (join and on) is confusing and doesn't always work; I'd recommend always using the 'new' syntax anyway.
You can do this with join, but you have to only use that form. Since there is no join condition between t1 and t3, you need a cross join. This produces the cartesian product of the two tables, which isn't often what you want, but in this case since one the of the tables has a single row it seems appropriate.
CREATE VIEW VIEW6 AS
SELECT
t1.typ,
t1.specifikacia_typu,
t1.SPZ,
t2.trzba_auta/(t3.celkova_trzba/100) AS percenta
FROM AUTA t1
CROSS JOIN VIEW5_SUMA t3
JOIN VIEW4_SUMA_AUTA t2 ON t1.id_auto = t2.id_auto
Building views on top of views isn't always a good idea and can cause performance issues.

Resources