【发布时间】:2010-09-09 12:55:40
【问题描述】:
我有一个使用 NHibernate Criteria 创建的 SQL 查询时遇到问题:
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”)分组的最新记录。我正在选择最大 ID 以尝试获取最新记录(尽管这可能是其他内容,例如“MAX(UPDATED)”)。获得最新记录集后,我将进一步过滤它们(“WHERE COLC='something'”),并在结果中选择我需要的列。
如果有更好的方法来获得相同的结果,我会很高兴听到它。我的 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”的最大 ID,其中“COLB”与“something”匹配,所以我希望子查询返回 {3, 5}。最后,查询将只返回 ID 3 的记录(外部 WHERE 子句剔除了 5,因为 COLC 错误)。 COLB 和 COLC 中的实际数据无关紧要 - 我只是用它来进一步过滤结果。
我认为,在它的核心,我想要每组 COLA 的最新记录(最大 ID)
SELECT ID, COLA, COLB
FROM table
WHERE ID IN (SELECT MAX(ID) FROM table GROUP BY COLA)
ORDER BY ID DESC
【问题讨论】:
-
你能展示你的 NHibernate 代码吗?你想要的查询到底是什么,第二个?您几乎可以使用 HQL 将其复制并粘贴到 NHibernate 中。
-
我很想看到使用 LINQ 完成这项工作
-
@Rafael - 我添加了我能够在 NHibernate 中工作的内容。理想情况下,我想要第二个查询,但第一个是可以接受的并且产生相同的结果。第一个查询是一种解决方法,因为 NHibernate 总是将组属性放入 SELECT 列表中。我避免使用 HQL,因为我不喜欢使用“魔术字符串”。如果我绝对,肯定不能在标准上做到这一点,那么我想我没有太多选择。
-
将组属性放入选择列表有什么关系?难道你不能在事后抓住你想要/需要的东西吗?
-
@Gage - 在这种情况下很重要,因为它会产生无效的 SQL。当子查询返回多个列时,您不能执行“ID IN (SELECT ...”。如果有办法指定子查询中要比较的列,那么我可以使用它。SQL 错误是: "当不使用 EXISTS 引入子查询时,选择列表中只能指定一个表达式。"
标签: sql nhibernate criteria