Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

请问在sql dsl 里怎么聚合数据? #383

Closed
ghost opened this issue Apr 6, 2022 · 12 comments
Closed

请问在sql dsl 里怎么聚合数据? #383

ghost opened this issue Apr 6, 2022 · 12 comments

Comments

@ghost
Copy link

ghost commented Apr 6, 2022

请问我有一个查询订单列表的sql

database.from(OrderDao)
            .leftJoin(OrderDetailsDao, on = OrderDetailsDao.orderNo eq OrderDao.orderNo)
            .select()

查询出来的结果是这样的
image
请问我应该再用什么操作符可以将结果转换成{ orderNo:xx , orderTime:xxx , goodsList:[ ] }这样的结构?
突然想不通应该怎么写了...

@lookup-cat
Copy link
Member

lookup-cat commented Apr 7, 2022

先把每条记录查询出来转换成实体对象,然后再用kotlin的方法去进行聚合

database.from(OrderDao)
            .leftJoin(OrderDetailsDao, on = OrderDetailsDao.orderNo eq OrderDao.orderNo)
            .select()
            .map { Order.createEntity(it) }
            .groupBy { it.orderNo }
            .map { entry -> 
               val goodsList = entry.value.map { it.goodsName }
               val orderNo = entry.key
               val orderTime = entry.value.first().orderTime
            }

@ghost
Copy link
Author

ghost commented Apr 7, 2022

先把每条记录查询出来转换成实体对象,然后再用kotlin的方法去进行聚合

Each record is queried and transformed into an entity object, which is then aggregated using the Kotlin method

database.from(OrderDao)
            .leftJoin(OrderDetailsDao, on = OrderDetailsDao.orderNo eq OrderDao.orderNo)
            .select()
            .map { Order.createEntity(it) }
            .groupBy { it.orderNo }
            .map { entry -> 
               val goodsList = entry.value.map { it.goodsName }
               val orderNo = entry.key
               val orderTime = entry.value.first().orderTime
            }

这样写的话,到最后一个map,OrderDetails的信息就没有了

@vincentlauvlwj
Copy link
Member

第一次查询:

val orders = database.orders.filter { xxx }.toList()

第二次查询:

val orderIds = orders.map { it.id }
val orderDetails = database.orderDetails.filter { it.orderId.inList(orderIds) }.groupBy { it.orderId }

组装数据:

val results = orders.map { order -> 
    OrderDTO(
        orderId = order.orderId,
        orderTime = order.orderTime,
        goodsList = orderDetails[order.orderId]?.map { it.goodName }
    )
}

@ghost
Copy link
Author

ghost commented Apr 7, 2022

能用dsl实现吗?因为还有很多查询条件的判断,测试发现用序列性能不太好

@vincentlauvlwj
Copy link
Member

序列的底层实现是一样的,不存在性能不好的问题

@ghost
Copy link
Author

ghost commented Apr 7, 2022

大佬,我想写一个QueryRowSet转Map的扩展函数,这样我这个问题就能用dsl解决了,研究了半天也没写出来,请问可以实现吗?

@ghost
Copy link
Author

ghost commented Apr 7, 2022

序列的底层实现是一样的,不存在性能不好的问题

是这样的,我知道序列本身肯定不存在性能问题,但是我这个场景用序列的话,一次查询多个订单,每笔订单关联了多个商品id,获取商品图片的话需要通过这个商品id去查商品库,再通过商品库的图片id去文件库查询地址,这样一循环都有几十上百个这样的查询database.goods.find {goodsDao-> goodsDao.id eq it.goodsId!! }!!.imageInfo.url,就会很影响性能

@vincentlauvlwj
Copy link
Member

你不会用 inList 批量查询吗

@ghost
Copy link
Author

ghost commented Apr 7, 2022

 val orderList = database.order
            .filter { it.procurementId eq 13 }
            .drop(page * pageSize)
            .take(pageSize)
            .toList()
        val orderNos = orderList.map { it.orderNo }
        val orderDetails = database.orderDetails
            .filterIf(orderNos.isNotEmpty()) { it.orderNo inList orderNos  }
            .groupBy { it.orderNo }

        val result= orderList.map { order ->
            mapOf(
                "id" to order.id,
                "orderNo" to order.orderNo,
                "goodsList" to orderDetails[order.orderNo]!!.map {
                    mapOf(
                        "goodsId" to it.goodsId,
                        "goodsName" to it.goodsName,
                        "goodsPrice" to it.goodsPrice,
                        "goodsImgUrl" to database.goods.find {goodsDao-> goodsDao.id eq it.goodsId!! }!!.imageInfo.url
                    )
                }
            )
        }

这是整个的逻辑,请问用序列应该怎么增量查询?有这句database.goods.find {goodsDao-> goodsDao.id eq it.goodsId!! }!!.imageInfo.url整个查询是12s,不加的话是2s

@vincentlauvlwj
Copy link
Member

 val orderList = database.order
            .filter { it.procurementId eq 13 }
            .drop(page * pageSize)
            .take(pageSize)
            .toList()
        val orderNos = orderList.map { it.orderNo }
        val orderDetails = database.orderDetails
            .filterIf(orderNos.isNotEmpty()) { it.orderNo inList orderNos  }
            .groupBy { it.orderNo }

        val result= orderList.map { order ->
            mapOf(
                "id" to order.id,
                "orderNo" to order.orderNo,
                "goodsList" to orderDetails[order.orderNo]!!.map {
                    mapOf(
                        "goodsId" to it.goodsId,
                        "goodsName" to it.goodsName,
                        "goodsPrice" to it.goodsPrice,
                        "goodsImgUrl" to database.goods.find {goodsDao-> goodsDao.id eq it.goodsId!! }!!.imageInfo.url
                    )
                }
            )
        }

这是整个的逻辑,请问用序列应该怎么增量查询?有这句database.goods.find {goodsDao-> goodsDao.id eq it.goodsId!! }!!.imageInfo.url整个查询是12s,不加的话是2s

参考 #383 (comment)

@ghost
Copy link
Author

ghost commented Apr 7, 2022

我提的issue是dsl,你说用序列,我提出用序列在这个场景有性能问题,你就给我关了??

@vincentlauvlwj
Copy link
Member

我觉得我已经给出解答了:

  1. 序列并没有性能问题
  2. 你的场景可以用 inList 优化性能
  3. 我还给出了示范的代码,参考 请问在sql dsl 里怎么聚合数据? #383 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants