Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

row_number() over partition in hql

What is the equivalent of row_number() over partition in hql I have the following query in hql:

select s.Companyname, p.Productname, sum(od.Unitprice * od.Quantity - od.Discount) as SalesAmount FROM OrderDetails as od inner join od.Orders as o inner join od.Products as p " +
                                                              "inner join p.Suppliers as s" +
                                                      " where o.Orderdate between '2010/01/01' and '2014/01/01' GROUP BY s.Companyname,p.Productname"

I want to do partition by s.Companyname where RowNumber <= n.

like image 671
user3425420 Avatar asked Apr 01 '14 06:04

user3425420


People also ask

What is ROW_NUMBER () over partition by in SQL?

PARTITION BY It is an optional clause in the ROW_NUMBER function. It is a clause that divides the result set into partitions (groups of rows). The ROW_NUMBER() method is then applied to each partition, which assigns a separate rank number to each partition.

Can we use Rownum in hive?

Use the ROW_NUMBER() function to get top rows by partition in Hive. SELECT t2. column_A as column_A, t2. cnt as cnt FROM ( SELECT t.

How does the ROW_NUMBER function work?

ROW_NUMBER numbers all rows sequentially (for example 1, 2, 3, 4, 5). RANK provides the same numeric value for ties (for example 1, 2, 2, 4, 5). ROW_NUMBER is a temporary value calculated when the query is run. To persist numbers in a table, see IDENTITY Property and SEQUENCE.


2 Answers

As far as I know you cannot use row_number() neither in HQL nor in JPQL. I propose to use a native SQL query in this case:

@PersistenceContext
protected EntityManager entityManager;
...

    String sQuery = "SELECT q.* FROM (" +
            "SELECT s.company_name, " +
               "p.product_name, " +
               "sum(od.unit_price * od.quantity - od.discount) as SalesAmount, " +
               "row_number() OVER (partition by s.company_name) as rn " +
            "FROM OrderDetails od " +
            "INNER JOIN Orders o ON o.id = od.order_id " +
            "INNER JOIN Products p ON p.id = od.product_id " +
            "INNER JOIN Suppliers s ON s.id = p.supplier_id " +
            "WHERE o.order_date between '2010/01/01' and '2014/01/01') as q " +
        "WHERE rn <= :n";

    List<ResultDbo> results = new ArrayList<>();
    Query query = entityManager.createNativeQuery(sQuery);
    query.setParameter("n", n);
    List<Object[]> resultSet = query.getResultList();
    for (Object[] resultItem : resultSet) {
        ResultDbo result = new ResultDbo();
        result.setCompanyName((String) resultItem[0]);
        result.setProductName((String) resultItem[1]);
        result.setSalesAmount((String) resultItem[2]);
        results.add(result);
    }

If you ever try to use OVER() in HQL you'll almost certainly get some validation exception like java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: OVER near line 1, column 42 ...

like image 122
naXa Avatar answered Sep 23 '22 13:09

naXa


Row number by partition looks like this:

row_number() over (partition by s.Companyname)

You can not use window function row_number in where clause, so you have to do subquery with filter by its value:

select * from (
  -- here is your query
  select 
    ...,
    row_number() over (partition by s.Companyname) as rowNum
  from ...
  where ...
) as res
where rowNum <= n
like image 42
Lyubov Averina Avatar answered Sep 24 '22 13:09

Lyubov Averina