繁体   English   中英

用于返回计数和最大值的 SQL 语句

[英]A SQL statement to return a count and a max

我使用 Spring 引导和 Hibernate。 目前我对数据库有 3 个单独的请求:

  1. 从表 aaa 中获取所有特定(带有一些 WHERE 条件)数据
  2. 从表 bbb 中获取所有特定(带有一些 WHERE 条件)数据
  3. 从点 1 和点 2 获取具有相同条件的 WHERE 子句找到的最大记录日期。

声明#1

SELECT count(a.id) as dateTo
from (
        SELECT a.date_to
        FROM aaa a
                 JOIN ramp r on a.ramp_id = r.id
                 JOIN warehouse w on r.warehouse_id = r.warehouse_id
        WHERE w.id = 222
          AND a.date_from >= '2022-08-20T00:00'      
    ) allDates

声明#2

SELECT count(b.id) as dateTo
from (
        SELECT b.date_to
        FROM bbb b
        WHERE tw.warehouse.id = :warehouseId
            AND tw.status = 'AVAILABLE'
    ) allDates

声明#3

SELECT MAX(date_to) as dateTo
from (
        SELECT a.date_to
        FROM aaa a
                 JOIN ramp r on a.ramp_id = r.id
                 JOIN warehouse w on r.warehouse_id = r.warehouse_id
        WHERE w.id = 222
          AND a.date_from >= '2022-08-20T00:00'      
        UNION
        SELECT b.valid_to as date_to
        FROM bbb b
        WHERE b.warehouse_id = 222
          AND tw.status = 'AVAILABLE'
    ) allDates

是否有可能用一个语句来完成所有这一切? 我使用 MySql 5.7,所以 CTE 不可用。

我在 Spring 中的代码:

final long numberOfa = ...
final long numberOfB = ...
final LocalDate maxDate = ... 

预期结果:

final MyObjectWithAllThreeValues myObject = repository.getAllDataWithOneQuery

您可以在子查询中存储一个标志(称为“ which_tab ”),然后在SUM聚合 function 中使用CASE表达式来计算行数。

SELECT MAX(date_to) AS dateTo,
       SUM(CASE WHEN which_tab = 'a' THEN 1 END) AS count_a_id,
       SUM(CASE WHEN which_tab = 'b' THEN 1 END) AS count_b_id
from (
        SELECT 'a' AS which_tab, a.date_to
        FROM aaa a
                 JOIN ramp r on a.ramp_id = r.id
                 JOIN warehouse w on r.warehouse_id = r.warehouse_id
        WHERE w.id = 222
          AND a.date_from >= '2022-08-20T00:00'      
        UNION ALL
        SELECT 'b' AS which_tab, b.valid_to AS date_to
        FROM bbb b
        WHERE b.warehouse_id = 222
          AND tw.status = 'AVAILABLE'
    ) allDates

注意:如果您应用UNION的两个子查询中的行不重叠,则最好使用UNION ALL ,因为它可以避免额外的不必要的聚合。

所有查询都返回一行,因为您在没有任何GROUP BY的情况下聚合了所有行。 因此,您可以进行两种聚合,然后交叉连接两个结果行:

SELECT
  a_agg.cnt AS count_a,
  b_agg.cnt AS count_b,
  GREATEST(a.max_date, b.max_date) AS max_date
FROM 
(
  SELECT COUNT(*) AS cnt, MAX(a.date_to) AS max_date
  FROM aaa a
  JOIN ramp r ON r.id = a.ramp_id
  JOIN warehouse w ON w.warehouse_id = r.warehouse_id
  WHERE w.id = 222
  AND a.date_from >= TIMESTAMP '2022-08-20 00:00:00'      
) a_agg
CROSS JOIN
(
  SELECT COUNT(*) AS cnt, MAX(b.date_to) AS max_date
  FROM bbb b
  WHERE b.warehouse.id = :warehouseId
  AND b.status = 'AVAILABLE'
) b_agg;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM