I have written an SQL query in which I use the HAVING clause.
However, I have not found practical examples of the use of HAVING in the Exhibited documentation.
My query should return the following:
SELECT pc.*
FROM "pedido" p
INNER JOIN pedido_contestacao pc ON t.id = pc.pedido_id
WHERE p.number = '1234'
GROUP BY pc.id
HAVING (
SELECT status
FROM contestacao_event ce
WHERE ce.pedido_contestacao_id = pc.id
ORDER BY ce.created_at DESC
limit 1
) IN ('CAPTURED', 'EXPIRED')
My biggest difficulty is writing the HAVING sub query. I saw that there is a function called wrapAsExpression, but I can't use it in this scenario. My query so far looks like this:
val contestacaoEventTable = ContestacaoEventTable.alias("det")
val pedidoContestacaoTable = PedidoContestacaoTable.alias("tdt")
val subQuery = contestacaoEventTable
.slice(contestacaoEventTable[ContestacaoEventTable.status])
.selectAll()
.andWhere {
ContestacaoEventTable.id eq pedidoContestacaoTable[PedidoContestacaoTable.id]
}.orderBy(ContestacaoEventTable.createdAt to SortOrder.DESC)
.limit(1)
.alias("statusQuery")
val status = contestacaoEventTable[ContestacaoEventTable.status]
PedidoTable
.innerJoin(PedidoContestacaoTable)
.slice(PedidoContestacaoTable.columns)
.selectAll()
.groupBy(PedidoContestacaoTable.id)
.andWhere { PedidoTable.number eq '1234' }
.having {
// wrapAsExpression(subQuery.slice(status).selectAll()).inList(listOf("CAPTURED", "EXPIRED"))
}.map {
println(it[PedidoContestacaoTable.id])
}
I don't know what else to do to make it work.
sorry for the delay! You are the man! Saved my development!
I made some adaptations to your suggestion.
My solution was as follows:
fun <T : Any> wrapAsExpressionWithColumnType(query: Query, columnType: IColumnType) =
object : ExpressionWithColumnType<T?>() {
private val expression = wrapAsExpression<T>(query)
override fun toSQL(queryBuilder: QueryBuilder) = expression.toSQL(queryBuilder)
override val columnType: IColumnType = columnType
}
And the final code for the query:
transaction {
val contestacaoEventTable = ContestacaoEventTable.alias("det")
val pedidoContestacaoTable = PedidoContestacaoTable.alias("tdt")
val contestacaoEventTransacaoId = contestacaoEventTable[ContestacaoEventTable.contestacaoTransacaoId]
val contestacaoEventCreatedAt = contestacaoEventTable[ContestacaoEventTable.createdAt]
val contestacaoEventStatus = contestacaoEventTable[ContestacaoEventTable.status]
val pedidoContestacaoId = pedidoContestacaoTable[PedidoContestacaoTable.id]
val pedidoContestacaoTransacaoId = pedidoContestacaoTable[PedidoContestacaoTable.transacaoId]
val subQuery = contestacaoEventTable
.slice(contestacaoEventTable[ContestacaoEventTable.status])
.selectAll()
.andWhere { contestacaoEventTransacaoId eq pedidoContestacaoId }
.orderBy(contestacaoEventCreatedAt to SortOrder.DESC)
.limit(1)
.alias("subQuery")
PedidoTable
.innerJoin(pedidoContestacaoTable, { PedidoTable.id }, { pedidoContestacaoTransacaoId })
.slice(pedidoContestacaoId)
.selectAll()
.groupBy(pedidoContestacaoId)
.andWhere { PedidoTable.number eq '1234' }
.having {
wrapAsExpressionWithColumnType<String>(subQuery.query, contestacaoEventStatus.columnType)
.inList(listOf(PedidoStatus.CAPTURED.name, PedidoStatus.EXPIRED.name))
}.toList().size
}
Thanks a lot for the help . Hope I can help other people.