How to write Order by expression in JPQL - sql-order-by

PostgreSQL and MySQL offers to write expression into ORDER BY clause in SQL query. It allows to sort items by some column but the special values are on the top. The SQL looks like this one. ( works in Postgres )
select * from article order by id = 4, id desc;
Now I want to write it in the JPQL but it doesn't work. My attempt is:
#NamedQuery(name = "Article.special", query = "SELECT a FROM Article a ORDER BY ( a.id = :id ) DESC, a.id DESC")
This is JPA 1.0 with Hibernate driver. Application server throws this exception on deploy.
ERROR [SessionFactoryImpl] Error in named query: Article.special
org.hibernate.hql.ast.QuerySyntaxException: unexpected AST node: = near line 1, column 73 [SELECT a FROM cz.cvut.fel.sk.model.department.Article a ORDER BY ( a.id = :id ) DESC, a.id DESC]
at org.hibernate.hql.ast.QuerySyntaxException.convert(QuerySyntaxException.java:54)
Thanks a lot.

For a named query, (ORDER BY ( a.id = :id ) or ORDER BY (:id )) won't work as DSC/ASC can't be parametrized at run-time.
1) Dynamic way if ordering element varies at runtime.
String query = "SELECT a FROM Article a ORDER BY "+orderElement+" DESC, a.id DESC";
entityManager.createQuery(query).getResultList();
2) Static way in entity bean if ordering element is fixed.
Field level:
#OrderBy("id ASC")
List<Article> articles;
Method level:
#OrderBy("id DESC")
public List<Article> getArticles() {...};

Related

Spring MVC, Select Special Columns in Native SELECT Query

this is my native SELECT Query in Repository
#Modifying
#Query(value = "SELECT * FROM tasks WHERE title LIKE '%Java%' ORDER BY id DESC ", nativeQuery = true)
List<Task> listAllTasks();
this works ok, but when I use custom column name instead of *, like this
#Modifying
#Query(value = "SELECT title FROM tasks WHERE title LIKE '%Java%' ORDER BY id DESC ", nativeQuery = true)
List<Task> listAllTasks();
I have this error :
org.postgresql.util.PSQLException: The column name id was not found in this ResultSet.
any Help?
The resultset doesn't have the "id" in it, you have to provide it.
You should change the way you are declaring your SQL:
SELECT t.title, t.id FROM tasks t WHERE t.title LIKE '%Java%' ORDER BY t.id DESC
Check out this sort example:Native Queries
Select * from Entity -> returns a List of Entity
Example:
#Query(select * from tasks)
List<Task> findAllTasks();
Select column from Entity -> returns a List of Types of the entity.
Example:
#Query(select t.title from tasks t)
List<String> findTitle_AllTasks();
title is of the type String
Select multiple columns from Entity -> returns an Object[] holding the data
Example:
#Query(select t.id, t.title from tasks t)
List<Object[]> findIdTitle_AllTasks();
So, you are retrieving String type data - title and asking to return a List of Task type. This is causing the problem. You can actually check the hibernate docs under HQL and JPQL to understand this.
Plus, you are doing a SELECT (DQL operation). #Modifying is rudimentary here as it is used for DML operations using Data JPA - UPDATE/DELETE.

How to select different fields using .Concat for Union All query

I’m doing some preliminary work getting data consumption ready from a webAPI controller in MVC. I’m using a linq query that mimics a union query that uses two joins. However, I need the select statement to ask for a different field on each side of the union. This works fine in SSMS when I run the query, but when I create the query in linq it will not allow the fields to be different. It gives an error saying that each anonymous type requires a receiver of the same type. This is referring to the two anonymous types created via select new { }… Here’s the two queries.
In SQL:
Select m.Last_Name, first_name, m.dc_number, Dept_Job as JobOrStatus FROM
Master_Roster m
INNER JOIN Class_Assignment a on m.dc_number = a.dc_number
where a.subject_am = 'y1'
AND Start_Date_AM <= '1/31/18'
UNION ALL
Select m.Last_Name, first_name, m.dc_number, status_am FROM Master_Roster m
INNER JOIN Attend_am_y1 at on m.dc_number = at.dc_number
where at.class_date_am >= '1/1/18'
AND at.class_date_am <= '1/31/18'
ORDER BY Last_Name
In linq:
(from m in db.Master_Roster
join c in db.Class_Assignment
on m.dc_number equals c.dc_number
orderby m.Last_Name
where c.Subject_AM == "y1"
select new { m.dc_number, m.Last_Name, m.First_Name }).Concat(
from m in db.Master_Roster
join a in db.attend_am_y1 on m.dc_number equals a.dc_number
orderby m.Last_Name
where a.class_date_am >= date1 &&
a.class_date_am <= date2
select new { m.dc_number, m.Last_Name, m.First_Name });
If I were to add dept_job and status_am to the linq query, it throws aforementioned error. I’d like to do this without using a stored procedure. Any ideas?
Instead of putting into 2 anonymous types, put into the same viewmodel and concat. Eg:
Internal Class ConcatViewModel{
public int DcNumber {get;set;}
public string LastName {get;set;)
// etc...
}
Then:
select new ConcatViewModel{
DcNumber = m.dc_number,
LastName = m.Last_Name,
FirstName = m.First_Name,
Status = m.Dept_Job
}
and
select new ConcatViewModel{
DcNumber = m.dc_number,
LastName = m.Last_Name,
FirstName = m.First_Name,
Status = m.status_am
}
(assuming that status_am and Dept_Job are the same underlying type)

How to pass parameter to #Query annotation with hql

Here is my hql requete :
#Query("select a from Agent where a.visibility = true a order by a.id desc")
public Page<Agent> getAllAgents(Pageable pageable);
I want to select all agents that have visibility true.
In my Agent class a have Boolean visibility attribute with getVisibility and setVisibility functions. In my data base "visibility" stored as bit(1).
I tried a.visibility = 1, ... = '1', ...= 'TRUE', ...='true', ... is true. But i get this error :
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: a near line 1, column 74 [select a from com.GemCrmTickets.entities.Agent where a.visibility = true a order by a.id desc]
Any suggestions ? Thank you in advance.
Your query is not correct, you have an extra a between true and order by.... So the correct query would become like this
select a from Agent a where a.visibility = true order by a.id desc
Not sure if that fixes all your troubles. Check it out.
Change your query to this:
#Query("select a from Agent a where a.visibility = true order by a.id desc")
public Page<Agent> getAllAgents(Pageable pageable);
In your code, you have to write the Alice name of the table so add it.
#Query("select a from Agent a where a.visibility = true order by a.id desc")

Nested subquery not supported in hive

We have tried the below query in hive. but getting the error. please help me to resolve this in any other way.
select count(1) as OpenItems from issues i , issue_statuses s
where s.id = i.status_id
and s.name NOT IN ('Closed','Passed','Rejected','On
Hold','Baselined','Completed')
and i.project_id IN
(select id from projects3 from
CASE WHEN ${projectname} = 'All' then id in
(select p.id from members m, projects3 p ,users_1 u
where m.project_id = p.id and u.id = m.user_id and u.status = '1'
and u.id IN
(select u1.id from users_1 u1, Supervisor_hierarchy s1 where u1.mail = s1.email and s1.name = ${Superisorname})
group by p.id)
WHEN (${projectname} <>'All' and ${SubProject projectname} ='All') then id
IN (select id from (select id from project_closure where parent_id in (select id from projects where name = ${projectname}) group by id)a)
WHEN (${SubProject projectname}<>'All' and ${projectname}<> 'All') then id
IN (select id from(select id from project_closure where id in (select id from projects where name = ${SubProject projectname}) group by id)a)
END
order by id)
error: 6:5 Unsupported SubQuery Expression 'id': SubQuery expression refers to both Parent and SubQuery expressions and is not a valid join condition.
I know it is late but posting for anyone who face this issue.
This issue occurs when we encounter one or more of the below limitations of Hive Subqueries.
In this scenario, the reference to the parent query is used in Group By clause which comes under the 4th limitation.
Hive Subquery Limitations
These subqueries are only supported on the right-hand side of an expression.
IN/NOT IN subqueries may only select a single column.
EXISTS/NOT EXISTS must have one or more correlated predicates.
References to the parent query are only supported in the WHERE clause of the subquery.
Source: https://cwiki.apache.org/confluence/display/Hive/LanguageManual+SubQueries

The greatest row per group - further combining the result set with left join with other related table in Hibernate - HQL. Is it possible?

There two tables in my Oracle database product and product_image. They have one-to-many relationship from product to product_image. Therefore, the relationship can be mapped in Hibernate something like the following.
The product entity:
#Entity
#Table(name = "PRODUCT", catalog = "", schema = "WAGAFASHIONDB")
public class Product implements java.io.Serializable
{
#OneToMany(mappedBy = "prodId", fetch = FetchType.LAZY)
private Set<ProductImage> productImageSet;
}
#Entity
#Table(name = "PRODUCT_IMAGE", catalog = "", schema = "WAGAFASHIONDB")
public class ProductImage implements java.io.Serializable
{
#ManyToOne(fetch = FetchType.LAZY)
private Product prodId;
}
I need to query that can fetch a list of rows with the maximum prod_image_id (primary key of the prduct_image table) from each group of products in the product_image table.
This was my previous question. This can be done with the following SQL.
SELECT
pi.prod_image_id,
pi.prod_id, pi.prod_image
FROM
product_image pi
INNER JOIN (
SELECT
MAX(pi.prod_image_id) AS prod_image_id
FROM
product_image pi
GROUP BY
pi.prod_id
) prod_image
ON pi.prod_image_id=prod_image.prod_image_id
The answer to that question corresponds to the following correct HQL.
SELECT
pi.prodImageId,
pi.prodId
FROM
ProductImage pi
WHERE
pi.prodImageId in (
SELECT
MAX(pis.prodImageId)
FROM
Product p
INNER JOIN
p.productImageSet pis
GROUP BY
p.prodId
)
This brings the following result exactly as intended.
PROD_IMAGE_ID PROD_ID PROD_IMAGE
662 284 3562298873030291049_Winter.jpg
644 283 7551758088174802741_9392401244_SS_2505.jpg
595 124 298082252715152799_SS_5012.jpg
566 62 7826143854352037374_SS_5004-A.jpg
But what I actually need is that the result set retrieved by the above SQL/HQL needs to be combined with the product table with LEFT OUTER JOIN so that it can retrieve each product from the product table regardless of their images in the product_image table something like the following.
PROD_IMAGE_ID PROD_ID PROD_IMAGE
662 284 3562298873030291049_Winter.jpg
644 283 7551758088174802741_9392401244_SS_2505.jpg
595 124 298082252715152799_SS_5012.jpg
- 101 -
- 81 -
566 62 7826143854352037374_SS_5004-A.jpg
This could be done by the following native SQL but doesn't seem possible with HQL which allows a subquery only in the SELECT and the WHERE clauses, a subquery in the FROM clause is disallowed in HQL.
SELECT
t.prod_image_id,
p.prod_id,
t.prod_image
FROM
product p
LEFT OUTER JOIN(
SELECT
pi.prod_image_id,
pi.prod_id,
pi.prod_image
FROM
product_image pi
INNER JOIN (
SELECT
MAX(pi.prod_image_id) AS prod_image_id
FROM
product_image pi
GROUP BY
pi.prod_id
) prod_image
ON pi.prod_image_id=prod_image.prod_image_id
)t ON p.prod_id=t.prod_id ORDER BY p.prod_id DESC;
My Google search says this is not feasible with a single HQL statement. Is this possible somehow with HQL? Please confirm me.
You're right, you can't use subqueries in from clause.
http://docs.jboss.org/hibernate/orm/4.1/manual/en-US/html_single/#queryhql-subqueries
But you can use a separate query like:
select p
from Product p
where p.productImageSet is empty
to find the products that has no product image.
I would create an Oracle view that implements your query that gives you what you want with a simple select in HQL.
I'm currently having the same table relationship in MySQL. I'm currently trying to learn JPA. Accordingly, I'm using JPA 2.0 provided by Hibernate - version 4.2.7 final. The following JPQL,
select
p.prodId,
pi.productImageId,
p.prodName,
pi.prodImage
from
Product p
left join
p.productImageSet pi
where
pi.productImageId in (
select
max(productImageId) as productImageId
from
ProductImage
group by
prodId
)
or pi.productImageId is null
order by p.prodId
and the corresponding criteria query,
CriteriaBuilder criteriaBuilder=entityManager.getCriteriaBuilder();
CriteriaQuery<Tuple>criteriaQuery=criteriaBuilder.createTupleQuery();
Metamodel metamodel=entityManager.getMetamodel();
EntityType<Product>entityType=metamodel.entity(Product.class);
Root<Product>root=criteriaQuery.from(entityType);
SetJoin<Product, ProductImage> join = root.join(Product_.productImageSet, JoinType.LEFT);
List<Selection<?>>selections=new ArrayList<Selection<?>>();
selections.add(root.get(Product_.prodId));
selections.add(root.get(Product_.prodName));
selections.add(join.get(ProductImage_.prodImage));
selections.add(join.get(ProductImage_.productImageId));
criteriaQuery.multiselect(selections);
Subquery<Long>subquery=criteriaQuery.subquery(Long.class);
Root<ProductImage> subRoot = subquery.from(ProductImage.class);
subquery.select(criteriaBuilder.max(subRoot.get(ProductImage_.productImageId)));
subquery.groupBy(subRoot.get(ProductImage_.prodId).get(Product_.prodId));
Predicate []predicates=new Predicate[2];
predicates[0]=criteriaBuilder.in(join.get(ProductImage_.productImageId)).value(subquery);
predicates[1]=join.get(ProductImage_.productImageId).isNull();
criteriaQuery.where(criteriaBuilder.or(predicates));
criteriaQuery.orderBy(criteriaBuilder.desc(root.get(Product_.prodId)));
TypedQuery<Tuple> typedQuery = entityManager.createQuery(criteriaQuery);
List<Tuple> tuples = typedQuery.getResultList();
Both of them, JPQL and criteria query produce the following SQL query.
select
product0_.prod_id as col_0_0_,
productima1_.product_image_id as col_1_0_,
product0_.prod_name as col_2_0_,
productima1_.prod_image as col_3_0_
from
social_networking.product product0_
left outer join
social_networking.product_image productima1_
on product0_.prod_id=productima1_.prod_id
where
productima1_.product_image_id in (
select
max(productima2_.product_image_id)
from
social_networking.product_image productima2_
group by
productima2_.prod_id
)
or productima1_.product_image_id is null
order by
product0_.prod_id desc
resulting in fetching the desired result set as mentioned in the question - not in the way we can see in the usual RDBMS systems but it works.
This can be done, if the query statement is slightly modified. Accordingly the following criteria query does what exactly is needed.
CriteriaBuilder criteriaBuilder=entityManager.getCriteriaBuilder();
CriteriaQuery<ProductUtils>criteriaQuery=criteriaBuilder.createQuery(ProductUtils.class);
Metamodel metamodel = entityManager.getMetamodel();
Root<Product> root = criteriaQuery.from(metamodel.entity(Product.class));
ListJoin<Product, ProductImage> join = root.join(Product_.productImageList, JoinType.LEFT);
List<Selection<?>>selections=new ArrayList<Selection<?>>();
selections.add(root.get(Product_.prodId));
selections.add(root.get(Product_.prodName));
selections.add(join.get(ProductImage_.prodImage));
selections.add(join.get(ProductImage_.productImageId));
criteriaQuery.select(criteriaBuilder.construct(ProductUtils.class, selections.toArray(new Selection[0])));
Subquery<Long> subquery = criteriaQuery.subquery(Long.class);
Root<ProductImage> prodImageRoot = subquery.from(metamodel.entity(ProductImage.class));
subquery.select(prodImageRoot.get(ProductImage_.productImageId));
subquery.where(criteriaBuilder.equal(root, prodImageRoot.get(ProductImage_.prodId)), criteriaBuilder.lessThan(join.get(ProductImage_.productImageId), prodImageRoot.get(ProductImage_.productImageId)));
criteriaQuery.where(criteriaBuilder.exists(subquery).not());
criteriaQuery.orderBy(criteriaBuilder.desc(root.get(Product_.prodId)));
List<ProductUtils> list = entityManager.createQuery(criteriaQuery).getResultList();
This criteria query produces the following desired SQL query that does equally the same function which is needed as specified in the question.
select
product0_.prod_id as col_0_0_,
product0_.prod_name as col_1_0_,
productima1_.prod_image as col_2_0_ ,
productima1_.product_image_id as col_3_0_
from
social_networking.product product0_
left outer join
social_networking.product_image productima1_
on product0_.prod_id=productima1_.prod_id
where
not (exists (select
productima2_.product_image_id
from
social_networking.product_image productima2_
where
product0_.prod_id=productima2_.prod_id
and productima1_.product_image_id<productima2_.product_image_id))
order by
product0_.prod_id desc

Resources