My query won't work. Any ideas - hql

I am running a query on HQL but keep getting error messages.
Select *
From cdb_1234;
Where src_inst = '1' '2'
Group by acc
Having count (*) >1
The group by is a column in the dataset.
Please help
It says parseexception cannot recognise input

Your semicolon ; should come after the whole query is complete.
Also, you can't say "Select " if you are using a Group By clause.
You should use an aggregation phrase like count().
Also make sure src_inst is a string or text field, and not numeric. If it is a numeric field, you should use src_inst in (1, 2)
Guessing from the bad query, here is something probably you could try :
Select *
From cdb_1234
Where src_inst In ('1' ,'2')
And acc in (select acc From cdb_1234
Where src_inst In ('1' ,'2')
Group by acc
Having count (*) >1
)

Related

ORACLE - If in SELECT Statement

I have a select and I need to hide data in a column when some other column meets criteria. Is there a way to do that in Select statement ?
Here is what I tried:
SELECT acc.account_no, (case substr(acc.bank,18,3) when acc.account_no like'%011006000%' then ' ' end) "BANK_ACCOUNT", sum(acc.bills) "BILLS"
FROM BNK.Bank_Transaction acc
WHERE acc.Bill_Date BETWEEN '01.05.2018' AND '29.05.2018'
AND (acc.account_no LIKE '%011006000%'
OR acc.account_no LIKE '%011076000%')
I receive ORA-00905: missing keyword error in upper select.
You may need:
select case when account_no like '%011006000%'
then null
else substr(..)
end as yourColumn,
...
from ...

Get default value (and context column) when group by returns no records in Oracle

I have a query that I need for it to return a record even when there are no records. In the case where there are records, I simply want those records returned. On the other hand, when there are no records, I need it to still return a record but with the value for the "context" column (the GROUP BY column) equal to the value of the GROUP BY column that did not meet the criteria and a default value for aggregate function/column (e.g., 0). I tried a subquery:
SELECT
(
SELECT
CONTEXT,
SUM(VAL)
FROM
A_TABLE
WHERE
COL = 'absent'
GROUP BY
CONTEXT
)
FROM
DUAL;
but anything greater than one column in the subquery SELECT clause fails w/ a "too many values" message.
I also tried a UNION (with a little more context to more faithfully represent my situation):
SELECT
*
FROM
(
SELECT
CONTEXT,
SUM(VAL)
FROM
A_TABLE
WHERE
COL = 'absent'
GROUP BY
CONTEXT
UNION
SELECT
CONTEXT,
0
FROM
B_TABLE
)
AB_TABLE
INNER JOIN C_TABLE C -- just a table that I need to join to
ON
C.ID = AB_TABLE.C_ID
WHERE
C.ID = 10
AND ROWNUM = 1 -- excludes 2nd UNION subquery result when 1st returns record;
This one does work but I don't know why since the 2nd UNION subquery does not seem to be expressly connected w/ the first (I need the 2nd CONTEXT value to be the same as the 1st for the case where the 1st returns no records). The problem is that the real query does not return any records when I try to implement a similar strategy. I would like to see if there's a better way to approach this problem and perhaps get it to work for the real query (not included as it is too large and somewhat sensitive).
I am not sure I understand the question, but let's try.
I believe what you are saying is this. You have a table called A_TABLE, with columns CONTEXT, VAL, COL (and perhaps others as well).
You want to group by CONTEXT, and get the sum of VAL but only for those rows where COL = 'absent'. Otherwise you want to return a default value (let's say 0).
This can be done with conditional aggregation. The condition is in a CASE expression within the SUM, not in a WHERE clause (as you saw already, if you filter by COL='absent', in a WHERE clause, the query - past the WHERE clause - has no knowledge of the CONTEXT values that don't appear in any rows with COL = 'absent').
If the "default value" was NULL, you could do it like this:
select context, sum(case when col = 'absent' then value end) as val
from a_table
group by context
;
If the default value is anything other than NULL, the temptation may be to use NVL() around the sum. However, if VAL may be NULL, then it is possible that SUM(VAL) is NULL even when there are rows with COL = 'absent'. To address that possibility, you must leave the sum as NULL in those cases, and instead set the value to 0 (or whatever other "default value") only when there are NO rows with COL = 'absent'. Here is one way to do that. Still a standard "conditional" aggregate query:
select context,
case when count(case when col = 'absent' then 1 end) > 0
then sum(case when col = 'absent' then value end)
else 0 -- or whatever "default value" you must assign here
end as val
from a_table
group by context
;
Here's another way you could handle it that avoids the two additional tables (B_TABLE and C_TABLE).
SELECT context
, MAX(val)
FROM (
SELECT context
, SUM(val) as val
FROM a_table
WHERE col = 'absent'
GROUP BY context
UNION
SELECT context
, 0 as val
FROM a_table
) t
GROUP BY context
This assumes the default value you want to return is 0 and that any value in A_TABLE.VAL will be a positive integer.
http://sqlfiddle.com/#!4/c6ca0/20
SELECT b.context
, sum(a.val)
FROM b_table b
LEFT OUTER JOIN a_table a
ON a.context = b.context
AND a.col = 'absent'
GROUP BY b.context

Hibernate HQL GroupBy in Oracle

I created this query using HQL with Hibernate and Oracle
select c from Cat c
left join c.kittens k
where (c.location= 1 OR c.location = 2)
and (i.activo = 1)
group
by c.id,
c.name,
c.fulldescription,
c.kittens
order by count(e) desc
The problem comes with the fact that in HQL you need to specify all fields in Cat in order to perform a Group By, but fulldescription is a CLOB, and you cannot group by by a CLOB (I get a "Not a Group By Expression" error. I've seen a few solutions around for a pure SQL sentence but none for HQL.
A serious issue GROUP BY of HQL because if you specify your object in GROUP BY and in your SELECT field list behaviours are differents. In GROUP BY has considered only id field but in SELECT field list all fields are considered.
So you can use a subquery with GROUP BY to return only id from your object, so that result becomes an input for the main query, like the follow I write for you.
Pay attention there are some alias table (i and e) not defined, so this query doesn't work, but you know as fixed.
Try this:
select c2 from Cat c2
where c2.id in (
select c.id from Cat c
left join c.kittens k
where (c.location= 1 OR c.location = 2)
and (i.activo = 1) <-- who is i alias??
group by c.id)
order by count(e) desc <-- who is e alias???

Mathematical operation between two columns in a comparison

We're using Oracle 10g XE and we found that the following query didn't return any value:
SELECT ref.referencia,
ref.descripcio,
stock_reservat,
stock,
stock_p_rebre,
(SELECT count(*)
FROM ref_numeros_serie num
WHERE num.empresa=ref.empresa AND
num.referencia=ref.referencia AND
num.diposit=1 AND
nvl(num.actiu,'N')='S') cnt_nums_serie
FROM emp_referencies ref,
ref_stk_dip_acu stk
WHERE ref.empresa=1 AND
ref.referencia='1B' AND
stk.empresa=ref.empresa AND
stk.referencia=ref.referencia AND
stk.diposit=1 AND
-- Relevant part
(stk.stock - stk.stock_reservat) <> (SELECT count(*)
FROM ref_numeros_serie num
WHERE num.empresa=ref.empresa AND
num.referencia=ref.referencia AND
num.diposit=1 AND
nvl(num.actiu,'N')='S')
-- End of relevant part
GROUP BY ref.empresa,
ref.referencia,
ref.descripcio,
stk.stock,
stk.stock_reservat,
stock,
stock_p_rebre
So the comparison between the subtraction and the subquery was false. But if we swapped the subquery and the subtraction like this:
SELECT ref.referencia,ref.descripcio,
stock_reservat,
stock,
stock_p_rebre,
(SELECT count(*)
FROM ref_numeros_serie num
WHERE num.empresa=ref.empresa AND
num.referencia=ref.referencia AND
num.diposit=1 AND
nvl(num.actiu,'N')='S') cnt_nums_serie
FROM emp_referencies ref,
ref_stk_dip_acu stk
WHERE ref.empresa=1 AND
ref.referencia='1B' AND
stk.empresa=ref.empresa AND
stk.referencia=ref.referencia AND
stk.diposit=1 AND
-- Relevant part
(SELECT count(*)
FROM ref_numeros_serie num
WHERE num.empresa=ref.empresa AND
num.referencia=ref.referencia AND
num.diposit=1 AND
nvl(num.actiu,'N')='S') <> (stk.stock - stk.stock_reservat)
-- End of relevant part
GROUP BY ref.empresa,
ref.referencia,
ref.descripcio,
stk.stock,
stk.stock_reservat,
stock,
stock_p_rebre
The comparison is true and we get results.
We have tried the following cases:
Removing the second part of the subtraction so the left part of the comparison is stk.stock: we get results, correct
Changing the second part of the subtraction by a number like this stk.stock-2: we get results, correct
Swapping the left and right part of the comparison, as explained above: we get results, correct
Changing the arithmetic operator like this (stk.stock+stk.stock_reservat) <> subquery: no results, incorrect
Changing the subquery by a number like this (stk.stock-stk.stock_reservat) <> 2: we get results, correct
We have tried these cases with a 10g non-XE database and it has the same behaviour. With a 11g, on the other hand, it works perfectly fine.
So our conclusion is that with oracle 10g a comparison between an arithmetic operation between two columns and a subquery works only if the subquery is on the left side and the operation on the right side. Has anybody had a similar problem and how did you work around/fix it?
EDIT: I want to add that this happens when the subquery result is 0, we haven't had issues with it otherwise, i.e. it behaves as expected.
Your query could be simplified by using a subquery factoring clause, as in:
WITH ns AS (SELECT r.empresa, r.referencia, count(*) as CNT_NUMS_SERIE
FROM ref_numeros_serie n
INNER JOIN emp_referencies r
r.empresa = n.empresa AMD
r.referencia = n.referencia
WHERE n.diposit = 1 AND
NVL(n.actiu, 'N') = 'S'
GROUP BY r.empresa,
r.referencia)
SELECT ref.referencia,
ref.descripcio,
stock_reservat,
stock,
stock_p_rebre,
ns.CNT_NUMS_SERIE
FROM emp_referencies ref
INNER JOIN ref_stk_dip_acu stk
ON stk.empresa = ref.empresa AND
stk.referencia = ref.referencia
INNER JOIN ns
ON ns.empresa = ref.empresa AND
ns.referencia = ref.referencia
WHERE ref.empresa = 1 AND
ref.referencia = '1B' AND
stk.diposit = 1 AND
-- Relevant part
(stk.stock - NVL(stk.stock_reservat, 0)) <> ns.CNT_NUMS_SERIE
-- End of relevant part
GROUP BY ref.empresa,
ref.referencia,
ref.descripcio,
stk.stock,
stk.stock_reservat,
stock,
stock_p_rebre
This lets you pull the common expression (SELECT COUNT(*)...) out and treat it as a separate table. I think it makes the query easier to read and might save some execution time.
Share and enjoy.

Oracle: MIN() Statement causes empty row returns

I'm having a small issue with sorting the data returned from a query, with the aim of getting the oldest updated value in dataset so that I can update only that record. Here's what I'm doing:
WHERE ROWNUM = 1 AND TABLE1.ID != V_IGNOREID
AND TABLE1.LASTREADTIME = (SELECT MIN(TABLE1.LASTREADTIME) FROM TABLE1)
ORDER BY TABLE1.LASTREADTIME DESC;
It makes no difference as to whether the ORDER BY statement is included or not. If I only use the ROWNUM and equality checks, I get data, but it alternates between only two rows, which is why I'm trying to use the LASTREADTIME data (so that I can modify more than these two rows). Anybody have any thoughts on this, or any suggestions as to how I can use the MIN function effectively?
Cheers
select * from (
-- your original select without rownum and with order by
)
WHERE ROWNUM = 1
EDIT some explanation
I think the order by clause is applied on the resultset after the where clause. So if the rownum = 1 is in the same select statement with the order by, then it will be applied first and the order by will order only 1 row, which will be the first row of the unordered resultset.

Resources