What is the alternative to "NOT IN" in HQL Query? - hql

Below is the query in SQL
SELECT * FROM table_1 WHERE table_1_id NOT IN ( SELECT
table_1_id FROM table_2 WHERE some_other_id =
'81ae4876-52fe-4dcf-9a5e-8eb490176d46' )

Related

T-SQL to PL/SQL - Use temporary variables and the "INTO" expression to search the total of a query in Oracle DB

In sql below I return the search between the tables and then return the total of this already paginated.
The need to return this total is to paginate
That query is using sql server.
Sql server:
SELECT
bu.Id as 'BarcoUsuarioId',
Barco_Id as 'BarcoId',
bu.Usuario_Id as 'UsuarioId',
barco.Nome as 'NomeBarco'
into #tmpBarcoUsuario
FROM BARCO_USUARIO AS bu
inner join BARCO as barco on barco.Id = bu.Barco_Id
where bu.Usuario_Id = #usuarioId
declare #totalEmbarcacoes as int = (select count(*) from #tmpBarcoUsuario);
select
BarcoUsuarioId,
BarcoId,
UsuarioId,
NomeBarco,
#totalEmbarcacoes as TotalEmbarcacoes from #tmpBarcoUsuario
order by BarcoId
OFFSET #pageSize *(#pageNumber - 1) ROWS
fetch next #pageSize ROWS ONLY";
However, when using the Oracle database, I having some difficulty.
As can be seen in sql below, I already made the pagination query in oracle DB:
Oracle:
SELECT *
FROM(
SELECT ROWNUM rnum, b.*
FROM (
SELECT
barcoUser.ID BarcoUsuarioId ,
barcoUser.BARCO_ID BarcoId ,
barcoUser.USARIO_ID UsuarioId ,
barco.NOME NomeBarco
FROM BARCO_USUARIO barcoUser INNER JOIN EMBARCACAO barco ON barco.ID = barcoUser.BARCO_ID
WHERE (barcoUser.USARIO_ID=:usuarioId)ORDER BY BarcoId DESC
)b
)WHERE RNUM between :PageSize * (:PageNumber - 1) AND (:PageSize * :PageNumber)";
but how would I do to return the total of all this already paginated, as was done in sql server?
You can use the analytic count(*) function
SELECT *
FROM(
SELECT ROWNUM rnum, b.*
FROM (
SELECT
barcoUser.ID BarcoUsuarioId ,
barcoUser.BARCO_ID BarcoId ,
barcoUser.USARIO_ID UsuarioId ,
barco.NOME NomeBarco ,
count(*) over () TotalCount
FROM BARCO_USUARIO barcoUser
INNER JOIN EMBARCACAO barco ON barco.ID = barcoUser.BARCO_ID
WHERE (barcoUser.USARIO_ID=:usuarioId)
ORDER BY BarcoId DESC
)b
)
WHERE RNUM between :PageSize * (:PageNumber - 1)
AND (:PageSize * :PageNumber)
Note that Oracle has supported the OFFSET FETCH syntax since 12c if you want to minimize the changes between database engines. The rownum approach, however, may be faster than the OFFSET FETCH approach.

With clause not working with union

My query result is a union of several queries. I am facing the below error when I use WITH clause within a union. Any ideas why?
select column1 from TABLE_A
union
with abcd as (select * from TABLE_B)
select column2 from TABLE_A A, abcd
where abcd.m_reference = A.m_reference
ORA-32034: unsupported use of WITH clause
32034. 00000 - "unsupported use of WITH clause"
*Cause: Inproper use of WITH clause because one of the following two reasons
1. nesting of WITH clause within WITH clause not supported yet
2. For a set query, WITH clause can't be specified for a branch.
3. WITH clause can't sepecified within parentheses.
*Action: correct query and retry
Encapsulate your WITH statement in a dummy select.
select column1 from TABLE_A
union
select * from (
with abcd as (select * from TABLE_B)
select column2 from TABLE_A A, abcd
where abcd.m_reference = A.m_reference
)
Just define the CTE first, before the actual UNION query. Then use it as you would a regular table:
with abcd as (select * from TABLE_B)
select column1 from TABLE_A
union
select column2
from TABLE_A A
inner join abcd
on abcd.m_reference = A.m_reference
You can use multiple CTE as follows:
with cte1 AS (...),
cte2 AS (...)
select * from ...
Encapsulating it is the way to go if you have multiple WITHs; for example I just had to do this monstrosity to quickly pull in data from ID numbers from an Excel sheet
select * from (
with childvendor as (
select vendornumber, name From vendor where vendornumber = '0000800727'
)
select
v.vendornumber as parentvendor,
v.name as parentname,
cv.vendornumber as childvendor,
cv.name as childname
From
vendor v, childvendor cv
where
v.vendornumber = '0000800004'
)
UNION ALL
select * from (
with childvendor as (
select vendornumber, name From vendor where vendornumber = '0000800042'
)
select
v.vendornumber as parentvendor,
v.name as parentname,
cv.vendornumber as childvendor,
cv.name as childname
From
vendor v, childvendor cv
where
v.vendornumber = '0000800035'
)
And so on

Update with a minimum value from a union in Oracle

UPDATE table1 t SET t.columnA =
(SELECT MIN(columnB) FROM
(SELECT columnB FROM table2
WHERE table2.fk = t.pk
UNION ALL
SELECT columnB FROM table3
WHERE table3.fk = t.pk))
gives me ORA-00904: "T"."PK": invalid identifier . Any ideas on how to achieve this?
This is a problem of scoping. Oracle does not recognize the outer query alias more than one level of nesting deep.
If we assume that values are in both tables, then you can use LEAST() with subqueries:
UPDATE table1 t
SET t.columnA = LEAST( (SELECT MIN(columnB)
FROM table2
WHERE table2.fk = t.pk
),
(SELECT MIN(columnB)
FROM table3
WHERE table2.fk = t.pk
)
);
If not, you can modify your query by moving the correlation clause out one level:
UPDATE table1 t
SET t.columnA = (SELECT MIN(columnB)
FROM ((SELECT table2.fk, columnB FROM table2
) UNION ALL
(SELECT table3.fk, columnB FROM table3
)
) tt
WHERE tt.fk = t.pk
);

PL/SQL how do I select into table type local variable

PROCEDURE "ARCHIVE_CASE_LIST"
(
a_case_id_list IN INLISTNUMBERS
)
IS
l_customers INLISTNUMBERS;
INLISTNUMBERS is Oracle table of numbers;
How do I prepare pre-calculated list of customers and store them in l_customers, so that I don't need to use that long select statement in other update/select statements?
insert into table(l_customers) <-- fail
select distinct case1.customer_id into l_customers from case case1
where case1.case_id in (select column_value from table(a_case_id_list)) and
not exists (select 0 from case case2 where case2.customer_id = case1.customer_id and
case2.lifecycle_code not in (code_id('LIFECYCLE','A'), code_id('LIFECYCLE','D')));
update customer set customer.lifecycle_code = code_id('LIFECYCLE','A')
where customer.customer_id in (select column_value from table(l_customers));
open l_persons for
select person_id from person where person.customer_id in
(select column_value from table(l_customers));
Use a SELECT statement with BULK COLLECT:
select distinct case1.customer_id bulk collect into l_customers
from case case1
where case1.case_id in (select column_value from table(a_case_id_list)) and
not exists (select 0 from case case2 where case2.customer_id = case1.customer_id and
case2.lifecycle_code not in (code_id('LIFECYCLE','A'), code_id('LIFECYCLE','D')));

Oracle JOIN USING + Subquery : ora-00904 string: invalid identifier

i m having a little syntax problem in my query (simplified) :
select *
from table1 t1
inner join table2 t2 using (pk1)
inner join table3 t3 using (pk2)
where not exists (select1 from table4 t4 where t4.pk1 = t1.pk1)
By using the "using" keyword, oracle doesnt allow table identifier in front of the column name (eg : t1.pk1, only pk1 can be used)
If i write :
select *
from table1 t1
inner join table2 t2 using (pk1)
inner join table3 t3 using (pk2)
where not exists (select1 from table4 t4 where t4.pk1 = pk1)
This query will not give the expected results.
But since i am using an "exists" subquery, how can i join this subquery ?
Of course, i suppose i could write this query another way and avoid the exists, or i could NOT use "using".
But is it possible to have "join / using" combined with a subquery in the where clause ?
Edit : using Oracle 10gR2
Interesting problem! The best I can manage while still using USING is:
select * from
( select *
from table1 t1
inner join table2 t2 using (pk1)
inner join table3 t3 using (pk2)
) v
where not exists (select1 from table4 t4 where t4.pk1 = v.pk1)
You cannot use the table qualifiers with natural joins.
This query:
select 1 from table4 t4 where t4.pk1 = pk1
is being parsed as
select 1 from table4 t4 where t4.pk1 = t4.pk1
and NOT EXISTS over it always returns false if there is but a single record in table4.
Just use explicit JOIN conditions:
WITH table1 AS
(
SELECT 1 AS pk1
FROM dual
),
table2 AS
(
SELECT 1 AS pk1, 1 AS pk2
FROM dual
),
table3 AS
(
SELECT 1 AS pk2
FROM dual
),
table4 AS
(
SELECT 2 AS pk1
FROM dual
)
SELECT *
FROM table1 t1
JOIN table2 t2
ON t2.pk1 = t1.pk1
JOIN table3 t3
ON t3.pk2 = t2.pk2
WHERE NOT EXISTS
(
SELECT 1
FROM table4 t4
WHERE t4.pk1 = t1.pk1
)

Resources