NHibernate HQL SELECT TOP в подзапросе

Есть ли способ использовать SetMaxResult () во вспомогательном запросе? Я пишу запрос, чтобы вернуть все элементы заказа, принадлежащие самому последнему заказу. Поэтому мне нужно ограничить количество записей в подзапросе.

Эквивалентный sql выглядит примерно так:

SELECT i.*
FROM tbl_Orders o
JOIN tbl_OrderItems i on i.OrderId = o.Id
WHERE
o.Id in (SELECT TOP 1 o.Id FROM tbl_Orders o orderby o.Date desc)

Я использую hql специально, потому что api критериев не позволяет вам проецировать другой объект домена (я запрашиваю заказы, но хочу вернуть элементы заказа)

Я знаю, что hql не принимает «SELECT TOP», но если я использую SetMaxResult (), он будет применяться к внешнему запросу, а не к подзапросу.

Любые идеи?


person Andy    schedule 12.01.2010    source источник
comment
Связанные с NHibernate 3: stackoverflow.com/questions/7133983/   -  person Chris S    schedule 22.08.2011


Ответы (3)


Просто запросите заказы (и используйте SetMaxResult) и выполните «соединение выборки», чтобы убедиться, что все элементы заказа для выбранных заказов загружаются сразу. После этого по возвращенным заказам вы можете получить доступ к элементам заказа без отправки нового оператора SQL в базу данных.

person Fried Hoeben    schedule 12.01.2010
comment
Я считаю, что этот подход также должен позволить вам использовать API критериев, если вы этого хотите. - person Fried Hoeben; 12.01.2010
comment
Я пытался избежать этого маршрута, так как к элементам заказа, которые я оставил для краткости, применяется еще одно предложение WHERE. Так вы говорите, что невозможно применить ограничение к подзапросу? - person Andy; 12.01.2010
comment
Я не верю, что возможно установить ограничение на подзапрос, извините. Я боюсь, что вам понадобятся два запроса (один для выбора идентификаторов n заказов, которые вы хотите, а затем другой в строках заказов, где orderId в возвращаемом списке идентификаторов). Но в зависимости от общего количества строк заказа для верхних заказов, которые вам нужны, я, вероятно, сделал бы больше в коде (т.е. извлеку, объедините все строки заказов для первых n заказов, а затем отфильтруйте в коде, чтобы выбрать нужные вам строки заказа). - person Fried Hoeben; 12.01.2010
comment
Вы также можете просмотреть фильтры на лету (например, session.Filter (order.OrderLines, где this.amount ›2)) или предопределенные (hibernate.org/hib_docs/nhibernate/1.2/reference/en/html/). - person Fried Hoeben; 12.01.2010
comment
Спасибо, Фрид, разделение на две, кажется, хорошо работает для того, что я делаю. - person Andy; 12.01.2010

Начиная с NHibernate 3.2, вы можете использовать SKIP n / TAKE n в hql в конце запроса. Ваш запрос будет:

SELECT i.*
FROM tbl_Orders o
JOIN tbl_OrderItems i on i.OrderId = o.Id
WHERE
o.Id in (SELECT o.Id FROM tbl_Orders o orderby o.Date desc take 1)
person Pavel Bakshy    schedule 09.04.2015

Я тоже столкнулся с этой проблемой, но не нашел решения с использованием HQL ...

Подзапросы с top были бы очень хороши, так как это быстрее, чем сначала выполнить полное соединение. При выполнении полного соединения сначала SQL-серверы присоединяются к таблице, сортируют все строки и затем выбирают первые 30. С помощью подзапроса берутся первые 30 столбцов одной таблицы, а затем они объединяются с другой таблицей. Это намного быстрее!

Мой запрос с Subselect занимает около 1 секунды, запрос с объединением и сортировкой занимает 15 секунд! Так что присоединиться не было вариантом.

Я получил два запроса, первый подзапрос:

IQuery q1 = session.CreateQuery("select id from table1 order by id desc");
q1.SetMaxResults(100);

А потом второй запрос

IQuery q2 = session.CreateQuery("select colone, coltwo from table2 where table1id in (:subselect)");
q2.SetParameterList("subselect", q1.List());
person falstaff    schedule 03.02.2012