【问题标题】:Min and Max from same subquery来自同一子查询的最小值和最大值
【发布时间】:2022-09-27 17:09:39
【问题描述】:

如果查询具有支付的最高金额和最低金额的子选择,例如:

SELECT p.firstname, 
       p.lastname, 
       (SELECT MAX(pmt.amount) 
          FROM Payment pmt 
         WHERE pmt.person.id = p.id)  maxAmount,
       (SELECT MIN(pmt.amount) 
          FROM Payment pmt 
         WHERE pmt.person.id = p.id)  minAmount,
  FROM Person p

我们需要编写两个子查询。这在大型数据库上表现不佳。

普通 JPQL 中的任何解决方案?

  • 这回答了你的问题了吗? UNION to JPA Query
  • @HiranChaudhuri No. Union 将创建两个结果行。我需要一个结果行。

标签: java jpa jpql


【解决方案1】:

如果你有一个巨大的数据库,这个问题可能应该通过调整模式设计来解决。大多数 RDBMS 必须对 Payment 表进行全表扫描,以找到最小和最大 amount 值。您可以通过查看当前查询的EXPLAIN 输出来检查这一点。

由于您关心查询速度,您可以对模式进行非规范化并将maxAmount 和minAmount 列存储在Person 表中,或者创建一个新的PersonMinMaxPayment 表。然后,您可以在将新行插入Payment 表时更新这些,例如通过声明@PrePersist 或creating a trigger。

如果您的系统最终可以保持一致,那么还有更多的可能性。您可以延迟重新计算这些值,例如作为每天一次的批处理作业。

【讨论】:

  • 抱歉,仅限普通 JPQL。
  • @Grim 如果你弄明白了,请告诉我!
  • 我考虑一个视图,映射为只读类。
  • @Grim 视图不是 JPQL 解决方案
  • Postgres,使用 concat 更快。
【解决方案2】:

我用这个:

   SELECT p.firstname,
          p.lastname, 
          MAX(pmt.amount),
          MIN(pmt.amount)
     FROM Person p
LEFT JOIN p.payments pmt
    GROUP BY p.firstname, p.lastname

【讨论】:

    猜你喜欢
    • 2022-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-03
    • 2012-09-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多