JPQL JOINS with nested SELECT - jpql

Can I do something like this on JPQL?
SELECT NEW com.MyDTO(p.a, p.b, q.c, q.d)
FROM
(SELECT r.* FROM MyDTO1 r ) p
LEFT OUTER JOIN
(SELECT s.* FROM MyDTO2 s ) q
ON p.x = q.y
or similar?
(Above query has mixed with native and JPQL, so don't misunderstand)
I'm having a problem with this part I think.
FROM
(SELECT r.* FROM MyDTO1 r ) p
When I'm trying to execute I'm getting this error.
Exception Description: Syntax error parsing the query [.....], unexpected token [(]
Thank you!

No, you can't. Quote from the documentation:
Note that HQL subqueries can occur only in the select or where
clauses.

Yes you can!
You have to use native queries. Here is an example:
emf = Persistence.createEntityManagerFactory("TEST")
EntityManager em = emf.createEntityManager();
String queryString = "SELECT ID FROM ( SELECT * FROM ADDRESS WHERE ID < 0)";
Query query = em.createNativeQuery(queryString);
List<BigDecimal> result = query.getResultList();

Related

how to insert subQuery at join by "QueryDLS"

I'm using QueryDLS.
But I got some problems.
My Database server is MariaDB.
select s.* , a.user_id
from schedule s
left outer join(
select sch_idx, group_concat(user_id SEPARATOR ',') as user_id
from attendee a
group by sch_idx
) a
on s.idx = a.sch_idx;
and this is my code( Ofcoursly, It' is wrong)
public void selectJoin(){
JPAQueryFactory query = new JPAQueryFactory(em);
QSchedule qSchedule = QSchedule.schedule;
QAttendee qAttendee = QAttendee.attendee;
query.selectFrom(qSchedule)
.leftJoin(
query.select(
qAttendee.schIdx,
qAttendee.userId
).from(qAttendee)
.groupBy(qAttendee.schIdx)
).on(qSchedule.idx.eq(qAttendee.schIdx))
.fetch();
}
How can I insert subquery in the join like my sql sample?
And I Have to resolve Group_concat in QueryDSL
If I can not resolve my truoble by QueryDSL, Let me know what is best solutions.
please, I need your help!

CosmosDB Cassandra API - select in query throws exception

SELECT partition_int, clustering_int, value_string
FROM test_ks1.test WHERE partition_int = ? AND clustering_int IN ?
Prepared select query with in clause throws the following exception:
java.lang.ClassCastException: class com.datastax.oss.driver.internal.core.type.PrimitiveType cannot be cast to class com.datastax.oss.driver.api.core.type.ListType
(com.datastax.oss.driver.internal.core.type.PrimitiveType and com.datastax.oss.driver.api.core.type.ListType are in unnamed module of loader 'app')
at com.datastax.oss.driver.internal.core.type.codec.registry.CachingCodecRegistry.inspectType(CachingCodecRegistry.java:343)
at com.datastax.oss.driver.internal.core.type.codec.registry.CachingCodecRegistry.codecFor(CachingCodecRegistry.java:256)
at com.datastax.oss.driver.internal.core.data.ValuesHelper.encodePreparedValues(ValuesHelper.java:112)
at com.datastax.oss.driver.internal.core.cql.DefaultPreparedStatement.bind(DefaultPreparedStatement.java:159)
Using datastax oss driver - version 4.5.1 and cosmosDB.
The query works with cassadra as docker and works in cqlsh with CosmosDB.
Queries used:
CREATE TABLE IF NOT EXISTS test_ks1.test (partition_int int, value_string text, clustering_int int, PRIMARY KEY ((partition_int),clustering_int))
Prepare the statement: INSERT INTO test_ks1.test (partition_int,clustering_int,value_string) values (?,?,?)
Insert values: 1,1,”a” | 1,2,”b”
Prepare the statement: SELECT partition_int, clustering_int, value_string FROM test_ks1.test WHERE partition_int = ? AND clustering_int IN ?
Execute with parameters 1,List.of(1,2)
The expected parameter is an integer and not list of integers
Sample code of the select prepared statement:
final CqlSessionBuilder sessionBuilder = CqlSession.builder()
.withConfigLoader(loadConfig(sessionConfig));
CqlSession session = sessionBuilder.build();
PreparedStatement statement = session.prepare(
"SELECT partition_int, clustering_int,"
+ "value_string FROM test_ks1.test WHERE partition_int = ? "
+ "AND clustering_int IN ?");
com.datastax.oss.driver.api.core.cql.ResultSet rs =
session.execute(statement.bind(1,List.of(1, 2)));
Is there a workaround to use prepared select queries with in clause?
Thanks.
My suggestion would be to use an work around like this:
//IDS you want to use;
List<Integer> list = Arrays.asList(1, 2);
// Multiply the number of question marks
String markers = StringUtils.repeat("?,", list.size()-1);
//Final query
final String query = "SELECT * FROM test_ks1.test where clustering_int in ("+markers+" ?)";
PreparedStatement prepared = session.prepare(query);
BoundStatement bound = prepared.bind(list.toArray()).setIdempotent(true);
List<Row> rows = session.execute(bound).all();
I have tried on my end and it works with me.
Now on your case you also have another parameter before the IN that you need to include in the parameter list but only after build the markers placeholder.

SQL Oracle Sub-query

I am having a issue getting this Sub-query to run. I am using Toad Data Point -Oracle. I get syntax error. I have tried several different ways with no luck. I am knew to sub-query's
Select *
from FINC.VNDR_ITEM_M as M
where M.ACCT_DOC_NBR = A.ACCT_DOC_NBR
(SELECT A.CLIENT_ID,
A.SRC_SYS_ID,
A.CO_CD,
A.ACCT_NBR,
A.CLR_DT,
A.ASGN_NBR,
A.FISCAL_YR,
A.ACCT_DOC_NBR,
A.LINE_ITEM_NBR,
A.MFR_PART_NBR,
A.POST_DT,
A.DRCR_IND,
A.DOC_CRNCY_AMT,
A.CRNCY_CD,
A.BSL_DT
FROM FINC.VNDR_ITEM_F A
WHERE A.CLR_DT IN (SELECT MAX(B.CLR_DT)
FROM FINC.VNDR_ITEM_F AS B
where (B.ACCT_DOC_NBR = A.ACCT_DOC_NBR and B.FISCAL_YR=A.FISCAL_YR and B.LINE_ITEM_NBR = A.LINE_ITEM_NBR and B.SRC_SYS_ID =A.SRC_SYS_ID and B.POST_DT=A.POST_DT and B.CO_CD=A.CO_CD)
and (B.CO_CD >='1000' and B.CO_CD <= '3000' or B.CO_CD ='7090') and (B.POST_DT Between to_date ('08/01/2018','mm/dd/yyyy')
AND to_date ('08/31/2018', 'mm/dd/yyyy')) and (B.SRC_SYS_ID ='15399') and (B.FISCAL_YR ='2018'))
GROUP BY
A.CLIENT_ID,
A.SRC_SYS_ID,
A.CO_CD,
A.ACCT_NBR,
A.CLR_DT,
A.ASGN_NBR,
A.FISCAL_YR,
A.ACCT_DOC_NBR,
A.LINE_ITEM_NBR,
A.MFR_PART_NBR,
A.POST_DT,
A.DRCR_IND,
A.DOC_CRNCY_AMT,
A.CRNCY_CD,
A.BSL_DT)
Your syntax is broken, you put subquery just at the end. Now it looks like:
select *
from dual as m
where a.dummy = m.dummy
(select dummy from dual)
It is in incorrect place, not joined, not aliased. What you should probably do is:
select *
from dual m
join (select dummy from dual) a on a.dummy = m.dummy
You also have some redundant, unnecessary brackets, but that's minor flaw. Full code (I cannot test it without data access):
select *
from FINC.VNDR_ITEM_M M
join (SELECT A.CLIENT_ID, A.SRC_SYS_ID, A.CO_CD, A.ACCT_NBR, A.CLR_DT, A.ASGN_NBR,
A.FISCAL_YR, A.ACCT_DOC_NBR, A.LINE_ITEM_NBR, A.MFR_PART_NBR, A.POST_DT,
A.DRCR_IND, A.DOC_CRNCY_AMT, A.CRNCY_CD, A.BSL_DT
FROM FINC.VNDR_ITEM_F A
WHERE A.CLR_DT IN (SELECT MAX(B.CLR_DT)
FROM FINC.VNDR_ITEM_F AS B
where B.ACCT_DOC_NBR = A.ACCT_DOC_NBR
and B.FISCAL_YR=A.FISCAL_YR
and B.LINE_ITEM_NBR = A.LINE_ITEM_NBR
and B.SRC_SYS_ID =A.SRC_SYS_ID
and B.POST_DT=A.POST_DT
and B.CO_CD=A.CO_CD
and (('1000'<=B.CO_CD and B.CO_CD<='3000') or B.CO_CD='7090')
and B.POST_DT Between to_date ('08/01/2018', 'mm/dd/yyyy')
AND to_date ('08/31/2018', 'mm/dd/yyyy')
and B.SRC_SYS_ID ='15399' and B.FISCAL_YR ='2018')
GROUP BY A.CLIENT_ID, A.SRC_SYS_ID, A.CO_CD, A.ACCT_NBR, A.CLR_DT, A.ASGN_NBR,
A.FISCAL_YR, A.ACCT_DOC_NBR, A.LINE_ITEM_NBR, A.MFR_PART_NBR, A.POST_DT,
A.DRCR_IND, A.DOC_CRNCY_AMT, A.CRNCY_CD, A.BSL_DT) A
on M.ACCT_DOC_NBR = A.ACCT_DOC_NBR and M.CO_CD=A.CO_CD;
You need to add an alias to the SubSelect (or Derived Table in Standard SQL):
select *
from
( select .......
) AS dt
join ....

Hive multiple subqueries

I'm using Hive 0.9.0 and I'm trying to execute query i.e.
`SELECT a.id, b.user FROM (SELECT...FROM a_table) a, (SELECT...FROM b_table) b WHERE a.date = b.date;`
but it returns error "loop (...)+ does not match input....".
Does Hive support multiple subqueries in FROM just like Oracle DB?
Multiple subqueries allowed in hive.
I tested with below code,it works.
select * from (select id from test where id>10) a
join (select id from test where id>20) b on a.id=b.id;
Please post your exact code so that I can give relevant solution.
join subqueries is supported Absolutely.
I think the key problem is that u use SELECT...FROM.
The correct syntax is SELECT * FROM
SELECT a.id, b.user
FROM
(SELECT * FROM a_table) a
JOIN (SELECT * FROM b_table) b ON a.date = b.date;
If you want to obtain the full Cartesian product before applying the WHERE
clause, instead:
SELECT a.id, b.user FROM (SELECT...FROM a_table) a, (SELECT...FROM b_table) b WHERE a.date = b.date;
you should use 'join' in the middle, i.e.
SELECT a.id, b.user FROM (SELECT...FROM a_table) a join (SELECT...FROM b_table) b WHERE a.date = b.date;
above is not admissible in strict mode.

Converting a LEFT OUTER JOIN to Entity Framework

Here is a SQL Query I want to convert to EF4.3
command = database.GetSqlStringCommand(#"
select
H.AUTHENTICATION_ID,
USERNAME,
PERMISSIONS,
ORGANIZATION_IDENTIFIER,
O.ORGANIZATION_ID
from
AUTHENTICATION H
left join [AUTHORIZATION] T on H.AUTHENTICATION_ID=T.AUTHENTICATION_ID
join ORGANIZATION O on O.ORGANIZATION_ID = T.ORGANIZATION_ID
order by H.AUTHENTICATION_ID");
Here is the best LINQ I could come up with:
var query = from h in context.Authentications
join t in context.Authorizations on h.AuthenticationId equals t.Authentications.AuthenticationId
join o in context.Organizations on t.Organizations.OrganizationId equals o.OrganizationId
orderby
h.AuthenticationId
select new
{ AUTHENTICATION_ID = (Int16?)h.AuthenticationId,
h.Username,
t.Permissions,
o.OrganizationIdentifier,
OrganizationID = (Int16?)o.OrganizationId
};
I know i need to merge my first join (between Authorizations & Authentications) into, lets say x and apply DefaultIfEmpty but can't make out the syntax.
EDIT: Image for clarification:
Any help will be highly appreciated. Regards.
The basic syntax for a "left join" in Linq is like this:
from x in table1
join y in table2 on x.id equals y.id into jointable
from z in jointable.DefaultIfEmpty()
select new
{
x.Field1,
x.Field2,
x.Field3,
Field4 = z == null ? 0 : z.Field4
};
In your case, I'm a little confused because the entity relations you seem to be using in your Linq don't match the ones implied by your SQL; are the relationships here zero-or-one, zero-or-many, one-to-one, etc? Specifically, you're doing this:
from h in context.Authentications
join t in context.Authorizations on h.AuthenticationId equals t.Authentications.AuthenticationId
but your SQL implies that "Authentication" is the parent here with zero-or-more "Authorization" children, not the other way around, which would be more like:
from h in context.Authentications
from t in h.Authorizations.DefaultIfEmpty()
If you can give us a better idea of the data model and what data you expect to get out of it we can more easily explain how that query would look in Linq. Assuming that your relationships match what is implied by the SQL, you should be able to get what you want using the following Linq queries:
var query = from h in context.Authentications
from t in h.Authorizations.DefaultIfEmpty()
select new
{
h.AuthenticationId,
h.Username,
Permissions = t == null ? null : t.Permissions,
Organizations = t == null ? new EntitySet<Organization>() : t.Organizations
};
var query2 = from x in query
from o in x.organizations.DefaultIfEmpty()
select new
{
AUTHENTICATION_ID = (short?)x.AuthenticationId,
x.Username,
x.Permissions,
OrganizationIdentifier = o == null ? null : o.OrganizationIdentifier,
OrganizationID = o == null ? (short?)null : o.OrganizationID
};
Given the foreign keys that exist in the question diagram, how about something like this?
var query = from a in context.Authentications
select new
{
a.AuthenticationID,
a.Username,
a.Authorisations.Permissions ?? false,
a.Authorisations.Organisations.OrganisationIdentifier ?? 0
a.Authorisations.Organisations.OrganisationID ?? 0
};
I went ahead and moved the entire query to a Stored Procedure on the database. This solves the problem by avoiding LINQ and ObjectBuilder in the first place.

Resources