NHibernate Критерии "ВЫБРАТЬ ... ОТ (ВЫБРАТЬ ...") - PullRequest
2 голосов
/ 09 сентября 2010

У меня есть SQL-запрос. У меня проблемы с созданием с использованием критериев NHibernate:

SELECT ID, COLA, COLB, COLC
FROM table
WHERE COLC='something' AND ID IN (SELECT ID FROM (SELECT MAX(ID) as ID, COLA FROM table WHERE COLB='something' GROUP BY COLA) subquery)
ORDER BY ID DESC

У меня изначально был этот немного более простой запрос:

SELECT ID, COLA, COLB, COLC
FROM table
WHERE COLC='something' AND ID IN (SELECT MAX(ID) FROM table WHERE COLB='something' GROUP BY COLA)
ORDER BY ID DESC

Однако в случае NHibernate, еслиЯ использую «GROUP BY», он автоматически добавляет поле в оператор SELECT, и у меня нет возможности его остановить (насколько я могу найти).

По сути, мне нужно найти последнюю записьсгруппированы по некоторому произвольному столбцу (в данном примере «COLA»).Я выбираю максимальный идентификатор, чтобы попытаться получить последнюю запись (хотя это может быть что-то еще, например «MAX (ОБНОВЛЕНО)»).После получения набора последних записей я дополнительно фильтрую их ("WHERE COLC = 'что-то'") и выбираю нужные столбцы в результате.

Если есть лучший способ получить то же самоерезультаты, я был бы рад услышать это.Мои навыки SQL в лучшем случае посредственные.

В NHibernate я мог бы правильно выполнить два запроса, но кусок посередине - "SELECT ID FROM" - не работал бы.

Основной запрос:

DetachedCriteria.For<table>()
    .Add<table>(x => x.COLC == "something")
    .Add(LambdaSubquery.Property<table>(x => x.ID).In(subquery));

И подзапрос:

DetachedCriteria.For<table>()
    .Add<table>(x => x.COLB == "something")
    .SetProjection(Projections.ProjectionList()
        .Add(LambdaProjection.Max<table>(x => x.ID))
        .Add(LambdaProjection.GroupProperty<table>(x => x.COLA)));

Критерий подзапроса помещает «COLA» в список выбора (из-за GroupProperty), поэтому он не может использоваться самостоятельнои именно поэтому мне нужно выяснить, как выполнить «SELECT ID FROM (SELECT ...» в критериях. При объединении они выдают следующий недопустимый SQL (поскольку подзапрос возвращает более одного столбца):

SELECT ID, COLA, COLB, COLC
FROM table
WHERE COLC='something' AND ID IN (SELECT MAX(ID), COLA FROM table WHERE COLB='something' GROUP BY COLA)
ORDER BY ID DESC

Редактировать: Это также может помочь увидеть вид данных и результатов, которые я хочу:

ID  COLA  COLB          COLC
1   1     someone       someother
2   1     something     someone     (Matches subquery, but not the max. ID)
3   1     something     something   (Matches subquery and main query)
4   2     someone       something
5   2     something     someother   (Only matches subquery)
6   3     someone       someother

Результат, который я хочу здесь, является максимальным идентификатором для данногонабор «COLA», где «COLB» соответствует «что-то», поэтому я бы хотел, чтобы подзапрос возвратил {3, 5}. В конце запрос будет возвращать только запись для идентификатора 3 (внешнее предложение WHEREотсеивает 5, потому что COLC не так). Фактические данные в COLB и COLC не имеют значения- Я просто использую это для дальнейшей фильтрации результатов.

Я думаю, в основе этого, я хочу последнюю запись (max ID) для каждого набора COLA

SELECT ID, COLA, COLB
FROM table
WHERE ID IN (SELECT MAX(ID) FROM table GROUP BY COLA)
ORDER BY ID DESC

Ответы [ 2 ]

2 голосов
/ 13 сентября 2010

Я нашел альтернативное решение, так как не мог понять, как получить правильные результаты, используя API критериев в NHibernate - вместо этого используйте представление.

Представление просто использует запрос, который я первоначально хотел (без дополнительной фильтрации):

SELECT ID, COLA, COLB, COLC, ...
FROM table
WHERE ID IN
    (SELECT MAX(ID)
     FROM table
     GROUP BY COLA)

Затем в NHibernate я отобразил представление, как обычную таблицу (за исключением того, что я сделал его неизменным):

<class name="View" table="View" lazy="false" mutable="false">
    <id name="ID" type="Int32">
        <generator class="assigned"/>
    </id>
    <property name="COLA" type="String" length="100">
        <column name="COLA" />
    </property>
    <property name="COLB" type="String" length="100">
        <column name="COLB" />
    </property>
    <property name="COLC" type="String" length="100">
        <column name="COLC" />
    </property>
    <!-- Other fields -->
</class>

И создалкласс для сопоставления:

public class View
{
    public virtual int ID { get; set; }
    public virtual string COLA { get; set; }
    public virtual string COLB { get; set; }
    public virtual string COLC { get; set; }
    // Other fields
}

И, наконец, создал запрос для представления:

DetachedCriteria.For<View>()
    .Add<View>(x => x.COLB == "something")
    .Add<View>(x => x.COLC == "something")
    // Any other filtering criteria
    .AddOrder<View>(x => x.COLA, Order.Desc);

Я бы лучше использовал запрос с одним критерием в NHibernate, но эторабота сделана.

2 голосов
/ 09 сентября 2010

Итак, если вы ищете записи, которые имеют Max ID со значением из COLA, а также имеют COLB в нем с соответствующим MAX ID, вы можете использовать что-то вроде этого.Я попробовал это, используя некоторые из моих данных объекта и теста, и это, казалось, работало.Дайте мне знать, как это происходит.

РЕДАКТИРОВАТЬ

Для списка макс ID с COLA вы можете использовать этот запросСначала я покажу вам тот, который я использовал для тестирования, а затем, вероятно, ваш.

var maxes = (from x in ActiveRecordLinq.AsQueryable<Email_Group>()
                     group x by x.Headline
                     into g
                     select new {COLA = g.Key, MaxID = g.Max(z => z.TXDX.TXDX_ID)});

Ваш:

var maxes = (from x in ActiveRecordLinq.AsQueryable<table>()
                     group x by x.COLA
                     into g
                     select new {COLA = g.Key, MaxID = g.Max(z => z.ID)});

Я все еще работаю над полным запросом.Попытка сделать это за один звонок.Я опубликую, как только получу, но сейчас пятница, и я делаю это между работой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...