Группа QueryDSL по часам во временном диапазоне

У меня есть следующий SQL-запрос для группировки заказов по дате заказа и часу в день:

select to_char(o.order_date, 'YYYY-MM-DD HH24') order_date_hour,
  sum(o.quantity) quantity
from orders o
where o.order_date >= to_date('01.02.2016', 'DD.MM.YYYY')
  and o.order_date < to_date('03.02.2016', 'DD.MM.YYYY')
group by to_char(o.order_date, 'YYYY-MM-DD HH24')
order by to_char(o.order_date, 'YYYY-MM-DD HH24');

Пример результата выглядит следующим образом:

ORDER_DATE_HOUR | QUANTITY 
2016-02-01 06   | 10 
2016-02-03 09   | 20

Запрос работает, как и ожидалось, с помощью разработчика SQL. В QueryDSL я придумал следующий запрос:

SQLQuery q = queryFactory.createSQLQuery();
q.from(order);
q.where(order.orderDate.goe(Timestamp.valueOf(from)))
.where(order.orderDate.lt(Timestamp.valueOf(to)));

q.groupBy(to_char(order.orderDate, "YYYY-MM-DD HH24"));
q.orderBy(order.orderDate.asc());

List<Tuple> result = q.list(to_char(order.orderDate, "YYYY-MM-DD HH24"), order.quantity);

to_char — это метод, который я нашел в этой теме: https://groups.google.com/forum/#!msg/querydsl/WD04ZRon-88/nP5QhqhwCUcJ

Исключение, которое я получаю:

java.sql.SQLSyntaxErrorException: ORA-00979: не выражение GROUP BY

Я пробовал несколько вариантов запроса безуспешно.

Кто-нибудь знает, почему запрос не работает? Спасибо :)


person Robert M.    schedule 11.04.2016    source источник
comment
Никогда не использовал это, но из быстрого поиска должна ли последняя строка вашего кода иметь order.quantity.sum() ? На данный момент вы не агрегируете этот столбец, что, я думаю, объясняет ошибку.   -  person Alex Poole    schedule 11.04.2016
comment
Это может быть проблемой. Я все перепроверил и пока все работает. Спасибо :)   -  person Robert M.    schedule 12.04.2016


Ответы (1)


Вы можете использовать StringTemplate и DateTemplate для создания пользовательских выражений, как это делается в модульном тесте com.querydsl.sql.TemplateTest:

StringTemplate datePath = Expressions.stringTemplate(
    "to_char({0},'{1s}')", order.orderDate, ConstantImpl.create("YYYY-MM-DD HH24"));

DateTemplate from = Expressions.dateTemplate(
    Date.class, "to_date({0},'{1s}')", fromStr, ConstantImpl.create("DD.MM.YYYY"));

DateTemplate to = Expressions.dateTemplate(
    Date.class, "to_date({0},'{1s}')", toStr, ConstantImpl.create("DD.MM.YYYY"));

query.select(datePath.as("order_date_hour"), order.quantity.sum().as("quantity"))
 .from(order)
 .where(order.orderDate.goe(from)
     .and(order.orderDate.lt(to)))
    .groupBy(datePath)
    .orderBy(datePath.asc());

List<Tuple> results = query.fetch();

Вот распечатка для query.getSQL().getSQL():

select to_char("order".order_date,'YYYY-MM-DD HH24') order_date_hour, sum("order".quantity) quantity
from "order" "order"
where "order".order_date >= to_date(?,'DD.MM.YYYY') and "order".order_date < to_date(?,'DD.MM.YYYY')
group by to_char("order".order_date,'YYYY-MM-DD HH24')
order by to_char("order".order_date,'YYYY-MM-DD HH24') asc
person Meiko Rachimow    schedule 11.04.2016