Gathering the first experience mit jooq's multiset I try to figure out how to order the result set based on some criteria for the multiset. Consider a datastructure with a Product Table and each product can be assigned an arbitrary amount of storages.
When fetching products with this query:
List<ProductFilterItem> items =
dslContext
.select(
PRODUCT.ID,
PRODUCT.NAME
multiset(
select(
PRODUCT_STORAGE.ID,
PRODUCT_STORAGE.PRODUCT_ID,
PRODUCT_STORAGE.STOCK
PRODUCT_STORAGE.MIN_STOCK
)
.from(PRODUCT_STORAGE)
.where(PRODUCT_STORAGE.PRODUCT_ID.eq(PRODUCT.ID))
).as("storage").convertFrom(r -> r.into(ProductStorageItem.class))
)
.from(PRODUCT)
.where(queryCondition)
.fetchInto(ProductItem.class)
how to order the results based on criteria for the multiset.
Eg put those first that have a storages assigned.
orderBy(inline(3).desc())
gives the desired result, but to me it is not clear what the actual sort comparison is doing.
How to achieve more complex sorting, eg order by
min(
(PRODUCT_STORAGE.STOCK - PRODUCT_STORAGE.MIN_STOCK)
.divide(PRODUCT_STORAGE.MIN_STOCK.multiply(0.01))
)
or other computations based on stock values.
Thanks for your help!
Kind Regards, Andreas
MULTISET
orderingAs of jOOQ 3.15, MULTISET
are emulated in all dialects using either SQL/XML or SQL/JSON. While the order of XML documents is undefined, some SQL dialects may choose to define an order on JSON documents (eg PostgreSQL does it for JSONB
). But I'm not convinced it's a good idea in your case to depend on this implicit ordering (specifically, because jOOQ's emulations might change subtly to adapt to some edge cases), so better be explicit about what you want.
In standard SQL, you could extract data from your MULTISET
nested collection again in order to find some aggregate value like your MIN(...)
expression, but that seems quite laborious, and is currently not supported by jOOQ 3.15 (there are some standard SQL operators to operate on multisets, see https://github.com/jOOQ/jOOQ/issues/12031 )
MULTISET_AGG
alternative Since you want to order things by some aggregate value, why not use MULTISET_AGG
instead of MULTISET
? In the following case, you get an equivalent result, and ordering is well defined.
List<ProductFilterItem> items = dslContext
.select(
PRODUCT.ID,
PRODUCT.NAME
multisetAgg(
PRODUCT_STORAGE.ID,
PRODUCT_STORAGE.PRODUCT_ID,
PRODUCT_STORAGE.STOCK
PRODUCT_STORAGE.MIN_STOCK
).as("storage").convertFrom(r -> r.into(ProductStorageItem.class))
)
.from(PRODUCT)
.leftJoin(PRODUCT_STORAGE)
.on(PRODUCT_STORAGE.PRODUCT_ID.eq(PRODUCT.ID))
.where(queryCondition)
.groupBy(PRODUCT.ID, PRODUCT.NAME)
.orderBy(min(
PRODUCT_STORAGE.STOCK
.minus(PRODUCT_STORAGE.MIN_STOCK)
.divide(PRODUCT_STORAGE.MIN_STOCK.multiply(0.01))
))
.fetchInto(ProductItem.class)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.