sql "between statement" not working with spring - java

I have this sql which works fine(the result is given) when I execute the statement via the sql manager console.
SELECT * FROM (
SELECT s.*, #rank
:= #rank + 1 rank
FROM
quiz.score s, (SELECT #rank := 0) init
ORDER BY points DESC
) s
WHERE rank BETWEEN (select count(id) from score)-(10) AND (select count(id) from score)
ORDER BY rank;
If I try to execute the script via spring the result is always empty:
public List<Score> loadAllScoreLast(String pFrom, String pTo) {
return createJdbcTemplate().query(mLAUSFT, new Object[] { pFrom, pTo },
mScoreMapper);
}
pFrom is in this case (select count(id) from score)-(10) and pTo is (select count(id) from score)
I think I include pFrom and pTo the wrong way.
That is the original sql:
SELECT * FROM (
SELECT s.*, #rank
:= #rank + 1 rank
FROM
quiz.score s, (SELECT #rank := 0) init
ORDER BY points DESC
) s
WHERE rank BETWEEN ? AND ?
ORDER BY rank;
Could someone help me with that issue?
Thx in advance
Stefan

Why are pFrom and pTo strings? I guess it is some problem with the types and/or with the placeholders because the rest looks valid.
http://sqlfiddle.com/#!2/45e1b/1
You should check what plain SQL is generated.
I guess it might look like this (note the quotes).
SELECT * FROM (
SELECT s.*, #rank
:= #rank + 1 rank
FROM
quiz.score s, (SELECT #rank := 0) init
ORDER BY points DESC
) s
WHERE rank BETWEEN '(select count(id) from score)-(10)' AND '(select count(id) from score)'
ORDER BY rank;

Related

Oracle nested select with defined rows

My query looks like this:
SELECT
nvl(dd,'TOTAL') "Subject",
SUM(cnt) "Count,
SUM(pct) AS "%"
FROM
(
SELECT
dd,
COUNT(1) cnt,
round(RATIO_TO_REPORT(COUNT(1) ) OVER() * 100,2) AS pct
FROM
student p,
student_subject a
WHERE
p.sId = a.sId
AND student_type IN (
'1',
'2'
)
AND dd IN (
'MATH',
'SCIENCE',
'HISTORY'
)
GROUP BY
dd
ORDER BY
1
)
GROUP BY
ROLLUP(dd)
ORDER BY
1;
My Output should look like this:
Subject Count %
MATH 33 23.2%
SCIENCE 24 11.46%
HISTORY 56 44.778%
TOTAL 113 85.4.2%
If a particular subject doesnt have data it should still provide the row with 0 values like below
Subject Count %
MATH 33 23.20%
SCIENCE 0 0.00%
HISTORY 56 44.77%
TOTAL 113 85.42%
What I am getting rightnow is below with no SCIENCE row which is not desired ,
Subject Count %
MATH 33 23.20%
HISTORY 56 44.77%
TOTAL 113 85.42%
What I did is I removed the dd IN clause "AND dd IN (
'MATH',
'SCIENCE',
'HISTORY'
)"
However I am not able to get to the another inner select to select the 3 subjects.
If i understand the datamodel correctly when a student is not enrolled to a subject an entry for the subject wouldn't exist in student_subject table, which means the missing subject is not present in the deficit table as well. Hence technically it is not possible to join these two tables and report for a column value that doesn't exist in either of them.
Now to solve this,i use WITH clause to create another table to hold all the desired subjects and perform an outer join with the result set retrieved.
I have tested this and it works perfectly. Complete solution(Oracle 18c) with table and Query can be found in DBFIDDLE URL https://dbfiddle.uk/?rdbms=oracle_18&fiddle=df73453d7fa4e0478e74fa509b20a411.
WITH some_data AS (
SELECT 'MATH' AS subj
FROM dual
UNION ALL
SELECT 'SCIENCE' AS subj
FROM dual
UNION ALL
SELECT 'HISTORY' AS subj
FROM dual
)
SELECT
nvl(subj,'TOTAL') "Subject",
nvl(SUM(cnt),0) "Count",
nvl(SUM(pct),0) AS "%"
FROM
(SELECT
dd,
COUNT(1) cnt,
round(RATIO_TO_REPORT(COUNT(1) ) OVER() * 100,2) AS pct
FROM
student p,
student_subject a
WHERE
p.sId = a.sId
AND student_type IN (
'1',
'2'
)
AND dd IN (
'MATH',
'SCIENCE',
'HISTORY'
)
GROUP BY
dd
ORDER BY
1
) tab, some_data
where tab.dd(+) = some_data.subj
GROUP BY
ROLLUP(subj)
ORDER BY
1;
You need to use the list of tables as the inner view and use left join as follows:
SELECT NVL(DD, 'TOTAL') "Subject",
SUM(CNT) "Count",
SUM(PCT) AS "%"
FROM (
SELECT DD,
COUNT(1) CNT,
ROUND(RATIO_TO_REPORT(COUNT(1)) OVER() * 100, 2) AS PCT
FROM (
SELECT 'MATH' AS SUB FROM DUAL UNION ALL
SELECT 'SCIENCE' AS SUB FROM DUAL UNION ALL
SELECT 'HISTORY' AS SUB FROM DUAL
) SUBJECTS
LEFT JOIN STUDENT_SUBJECT A
ON SUBJECTS.SUB = A.DD
LEFT JOIN STUDENT P
ON P.SID = A.SID
WHERE STUDENT_TYPE IN (
'1','2'
)
GROUP BY DD
ORDER BY 1
)
GROUP BY ROLLUP(DD)
ORDER BY 1;
You have to use case statement to make it 0, If any of the subject is null then default it to 0. Let me know if you require a query. Am suggesting the logic so that you can try yourself.

Convert Postgres Query to JPQL

How to convert below PostreSQL query into JPQL? I mainly stuck with row_number(), partition and when case.
select p, c from product p left join
(
select
c.product_id, c.id, c.status, c.start_date,
row_number() over (partition by product_id order by (case status when 'EXPIRED' then 2 else 1 end) asc, start_date desc) as row_number
from contract c
order by product_id
) c
on
p.id = c.product_id and c.row_number = 1
order by p.id, c.start_date;

Can I add amounts from multiple tables in hql

I would like to perform a query in HQL similar to this in SQL:
SELECT (
SELECT COUNT(*) FROM EMPLOYER +
SELECT COUNT(*) FROM COMPANIES
)
FROM DUAL
When I add "FROM DUAL" to the query I get an error:
org.hibernate.hql.ast.QuerySyntaxException: DUAL is not mapped
And if I leave off the "FROM DUAL" I get:
org.hibernate.hql.ast.QuerySyntaxException: unexpected end of subtree
Any recommendations?
In SQL, subqueries need their own set of parentheses, so try this:
SELECT ((SELECT COUNT(*) FROM EMPLOYER) +
(SELECT COUNT(*) FROM COMPANIES)
)
If that doesn't work, resort to a from clause:
SELECT e.cnt + c.cnt
FROM (SELECT COUNT(*) as cnt FROM EMPLOYER
) e CROSS JOIN +
(SELECT COUNT(*) as cnt
FROM COMPANIES
) c
Since you didn't join the Company and Employee tables you'd better run two queries:
int companyCount = ((Number) getSession().createQuery("select count(*) from Company").uniqueResult()).intValue();
int employeeCount = ((Number) getSession().createQuery("select count(*) from Employee").uniqueResult()).intValue();
int totalCount = companyCount + employeeCount;
The (Number) is needed since PostgreSQL returns a BigInteger while HDSQLDB returns an Integer, but both are subclasses of Number.

How to join 2 row_numbers

Im trying to do a query where I want to join the row_numbers RN and RN1 so as to remove the duplicate rows as shown BOLD in the result set.
WITH CTE AS (
SELECT
PrevEndDate = LAG(edate,1) OVER (PARTITION BY id ORDER BY id)
, PrevStartDate = LAG(sdate,1) OVER (PARTITION BY id ORDER BY id)
, p.id, p.edate
, ROW_NUMBER() OVER (PARTITION BY p.id ORDER BY p.id) as RN1
FROM table p
)
SELECT
t.id, t.sdate, t.edate
, (ROW_NUMBER() OVER (PARTITION BY t.id ORDER BY t.id)) AS RN
, CTE.RN1
, CASE
WHEN CTE.PrevEndDate > t.sdate
THEN DATEDIFF(day,CTE.PrevStartDate,t.sdate)
ELSE
DATEDIFF(day,t.sdate,t.edate)
END
FROM table t
INNER JOIN CTE ON CTE.id= t.id AND CTE.edate= t.edate
--AND RN1 = RN
Thanks in Advance!
You can't define an alias in the select and then use it in from (or where for that matter). You can move it into a subquery. Something like:
with cte as (. . .)
SELECT . . .
FROM (SELECT t.*, ROW_NUMBER() OVER (PARTITION BY t.PRTCPNT_DCN ORDER BY t.PRTCPNT_DCN) as RN
FROM PRTCPNT_ELIG_SPAN_T t
) t INNER JOIN
CTE
ON CTE.PRTCPNT_DCN = t.PRTCPNT_DCN AND
CTE.PRTCPNT_ELIG_END_DATE = t.PRTCPNT_ELIG_END_DATE AND
CTE.RN1 = t.RN;

not all named parameters have been set hibernate in createSQLQuery

I am getting the error of not all named parameters have been set. Below is my code.
my SqlQuery which is running fine at mysql prompt, You can refer schema in the question SQL Query
SELECT t.*
FROM (
SELECT #lim := 2,
#cg := ''
) vars,
(select * from Table1 order by product,amount, make) t
WHERE CASE WHEN #cg <> product THEN #r := #lim ELSE 1 END > 0
AND (#r := #r - 1) >= 0
AND (#cg := product) IS NOT NULL
ORDER BY
product,amount, make
my java code
try {
context.dbl.startTransaction();
Session session = context.dbl.getSession();
//String sqlQuery = "from com.infibeam.inventoryservice.dbObjects.PopularBrandDO";
String sqlQuery = "SELECT t.* ";
sqlQuery=sqlQuery + "FROM (";
sqlQuery=sqlQuery + "SELECT #lim := 2,";
sqlQuery=sqlQuery + "#cg := ''";
sqlQuery=sqlQuery + ") vars, ";
sqlQuery=sqlQuery + "(select * from Table1 order by product,amount, make) t";
sqlQuery=sqlQuery + " WHERE CASE WHEN #cg <> product THEN #r := #lim ELSE 1 END > 0";
sqlQuery=sqlQuery + " AND (#r := #r - 1) >= 0 ";
sqlQuery=sqlQuery + " AND (#cg := product) IS NOT NULL ";
sqlQuery=sqlQuery + " ORDER BY product,amount, make";
//Query query = session.createQuery(sqlQuery);
SQLQuery query = session.createSQLQuery(sqlQuery);
listItems = query.list();
}catch(RuntimeException e) {
e.printStackTrace();
}
Below is the exception i am getting
org.hibernate.QueryException: Not all named parameters have been set: [] [SELECT t.* FROM (SELECT #lim := 2,#cg := '') vars, (select * from Table1 order by product,amount, make) t WHERE CASE WHEN #cg <> product THEN #r := #lim ELSE 1 END > 0 AND (#r := #r - 1) >= 0 AND (#cg := product) IS NOT NULL ORDER BY product,amount, make]
at org.hibernate.impl.AbstractQueryImpl.verifyParameters(AbstractQueryImpl.java:291)
at org.hibernate.impl.SQLQueryImpl.verifyParameters(SQLQueryImpl.java:199)
at org.hibernate.impl.SQLQueryImpl.list(SQLQueryImpl.java:143)
at com.infibeam.weaverbird.helper.PopularBrandFacetHelper.bootstrap(PopularBrandFacetHelper.java:48)
Thanks in advance...
The problem is the assignments with :=, which are by the way no standard SQL.
In SQL after a : always a parameter is expected, like in where value = :param and :param has the be set as a parameter then. Now hibernate is scanning the select and find colons where no set parameters follow.
Solution: Redesign your selection using hibernate standards.
You can use two different HQL queries.
First: Select all product: select distinct product from Table1
Second: For each product you do from Table1 where product = :prod, :prod you set as a parameter with the actual product, and with setMaxResults(2) you can limit the number of rows as you need.
Now it is many selects and not a single one, but nevertheless they might be faster than the single query (the single query is complicated and risks an inefficient search strategy in the database). And a big advantage, now it is purely HQL and so your program is portable to different databases.

Categories