我的选择查询是:
sql.select(COMPANY.NAME, COMPANY_CONTACT.NAME.as("CONTACT_INTERACTION"))
.from(COMPANY)
.join(COMPANY_CONTACT)
.on(COMPANY_CONTACT.COMPANY_ID.equal(COMPANY.ID))
.where(COMPANY.DELETED.equal(false));
'sql'的类型为 DSLContext 。
我试图从结果集中的所有这些中选择一个 COMPANY_CONTACT.NAME 。
答案 0 :(得分:0)
这就是我所说的TOP N per category query,其中N = 1
。
使用SQL的最简单解决方案是在PostgreSQL,Oracle,DB2中使用SQL标准LATERAL
,在SQL Server,Oracle中使用APPLY
。这是PostgreSQL版本:
SELECT
c.name,
cc.name AS contact_interaction
FROM company AS c
CROSS JOIN LATERAL (
SELECT cc.name
FROM company_contact cc
WHERE cc.company_id = c.id
ORDER BY cc.follow_up DESC
LIMIT 1
) AS cc
WHERE NOT c.deleted
或与jOOQ:
sql.select(COMPANY.NAME, COMPANY_CONTACT.NAME.as("CONTACT_INTERACTION"))
.from(COMPANY)
.crossJoin(lateral(table(
select(COMPANY_CONTACT.NAME)
.from(COMPANY_CONTACT)
.where(COMPANY_CONTACT.COMPANY_ID.eq(COMPANY.ID))
.orderBy(COMPANY_CONTACT.FOLLOW_UP.desc())
.limit(1)
).as(COMPANY_CONTACT)))
.where(not(COMPANY.DELETED))
.fetch();
DISTINCT ON
在PostgreSQL中,也可以使用DISTINCT ON
来编写每个类别查询的TOP 1,这是PostgreSQL的特定于供应商,并且受jOOQ支持:
SELECT DISTINCT ON (c.company_id) c.name, cc.name AS contact_interaction
FROM company AS c
JOIN company_contact AS cc
ON cc.company_id = c.id
WHERE NOT c.deleted
ORDER BY c.company_id, cc.follow_up DESC
或者在jOOQ中
sql.selectDistinct(COMPANY.NAME, COMPANY_CONTACT.NAME.as("CONTACT_INTERACTION"))
.on(COMPANY.COMPANY_ID)
.from(COMPANY)
.join(COMPANY_CONTACT)
.on(COMPANY_CONTACT.COMPANY_ID.eq(COMPANY.ID))
.where(not(COMPANY.DELETED))
.orderBy(COMPANY.COMPANY_ID, COMPANY_CONTACT.FOLLOW_UP.desc())
.fetch();
同样可以使用窗口函数来实现相同的功能,但是它比上面的解决方案要简单。但是,如果您希望结果中的TOP 1联系紧密,那么在PostgreSQL中不可避免地使用RANK()
函数。
A solution using window functions is also discussed in the previously linked blog post
注意
以上所有jOOQ代码均假定您已将此静态导入就位:
import static org.jooq.impl.DSL.*;