如何在多个日期使用相同的sql查询?

How to use same sql query for multiple dates?

提问人:Zaraki Kenpaachi 提问时间:11/2/2023 最后编辑:marc_sZaraki Kenpaachi 更新时间:11/2/2023 访问量:61

问:

我有以下选择查询

(
  SELECT COUNT(*) 
  FROM TABLE
  WHERE birth_date >= TO_DATE(:start_date1, 'YYYY/MM/DD')
  AND birth_date <= TO_DATE(:end_date1, 'YYYY/MM/DD')
) AS count1

我还需要找到 的计数,这将导致单独的变量start_date2end_date2count2

最好的方式是什么?count2

我重写了查询并用 和 替换了 和 。有没有其他方法可以不重写查询?start_date1end_date1start_date2end_date2

SQL Oracle 日期

评论

0赞 GrumpyCrouton 11/2/2023
我从未见过这种语法,您可以在 WHERE 子句中创建别名,这看起来很奇怪。反正你甚至没有使用别名,所以我不明白你的问题
0赞 Stickleback 11/2/2023
猜测这是一个更大的查询的一部分。我想说有三种选择可以考虑。创建一个可以使用参数化日期调用的存储过程,或者,如果出生日期的窗口一致,则使用分组依据并将日期与月初或月末对齐,或者使用声明变量的“立即执行”方法。
0赞 Zaraki Kenpaachi 11/2/2023
嗨,@GrumpyCoruton,是的,你是对的,这是更大的选择声明的一部分。

答:

0赞 Nekkanti Chakradhar 11/2/2023 #1

如果要避免重写整个查询,可以通过使用 CTE(公用表表达式)在单个查询中计算两个日期范围的计数来实现此目的。此方法不会完全消除重写查询,但会封装共享逻辑。下面是使用 CTE 的示例:

WITH DateRanges AS (
  SELECT
    (SELECT COUNT(*)
     FROM TABLE
     WHERE birth_date >= TO_DATE(:start_date1, 'YYYY/MM/DD')
       AND birth_date <= TO_DATE(:end_date1, 'YYYY/MM/DD')) AS count1,
    (SELECT COUNT(*)
     FROM TABLE
     WHERE birth_date >= TO_DATE(:start_date2, 'YYYY/MM/DD')
       AND birth_date <= TO_DATE(:end_date2, 'YYYY/MM/DD')) AS count2
)
SELECT count1, count2
FROM DateRanges;

此 SQL 查询使用名为 DateRanges 的 CTE 来计算 count1 和 count2,方法是对每个日期范围使用单独的 SELECT COUNT(*) 子查询,而无需重复整个查询逻辑。此方法允许您在单个查询执行中计算这两个计数。

0赞 Barmar 11/2/2023 #2

您可以使用返回每个日期的子查询进行联接,然后使用 .GROUP BY

SELECT t1.start_date, t1.end_date, COALESCE(COUNT(t2.birth_date), 0) AS count
FROM (
    SELECT :start_date1 AS start_date, :end_date1 AS end_date
    UNION ALL
    SELECT :start_date2 AS start_date, :end_date2 AS end_date
) t1
LEFT JOIN TABLE t2 ON t2.birth_date BETWEEN t1.start_date AND t1.end_date
GROUP BY t1.start_date, t1.end_date

评论

0赞 MT0 11/2/2023
这不是有效的 Oracle 查询,因为不受支持,并且不能在表/内联视图别名之前使用。除此之外,您还有一个语法错误,而不是 .IFNULLAS.,
0赞 Barmar 11/2/2023
对不起,没有注意到问题是Oracle,假设MySQL。
0赞 Barmar 11/2/2023
修复了语法错误并切换到 .COALESCE()
0赞 MT0 11/2/2023 #3

可以使用条件聚合仅查询一次表:

SELECT COUNT(
         CASE
         WHEN birth_date BETWEEN TO_DATE(:start_date1, 'YYYY/MM/DD')
                             AND TO_DATE(:end_date1, 'YYYY/MM/DD')
         THEN 1
         END
       ) AS count1,
       COUNT(
         CASE
         WHEN birth_date BETWEEN TO_DATE(:start_date2, 'YYYY/MM/DD')
                             AND TO_DATE(:end_date2, 'YYYY/MM/DD')
         THEN 1
         END
       ) AS count2
FROM   TABLE
WHERE  birth_date BETWEEN LEAST(TO_DATE(:start_date1, 'YYYY/MM/DD'), TO_DATE(:start_date2, 'YYYY/MM/DD'))
                      AND GREATEST(TO_DATE(:end_date1, 'YYYY/MM/DD'), TO_DATE(:end_date2, 'YYYY/MM/DD'))

如果要将其用作大型查询的一部分,则:CROSS JOIN

SELECT d.*,
       c.count1,
       c.count2
FROM   DUAL d
       CROSS JOIN (
         SELECT COUNT(
                  CASE
                  WHEN birth_date BETWEEN TO_DATE(:start_date1, 'YYYY/MM/DD')
                                      AND TO_DATE(:end_date1, 'YYYY/MM/DD')
                  THEN 1
                  END
                ) AS count1,
                COUNT(
                  CASE
                  WHEN birth_date BETWEEN TO_DATE(:start_date2, 'YYYY/MM/DD')
                                      AND TO_DATE(:end_date2, 'YYYY/MM/DD')
                  THEN 1
                  END
                ) AS count2
         FROM   TABLE
         WHERE  birth_date BETWEEN LEAST(TO_DATE(:start_date1, 'YYYY/MM/DD'), TO_DATE(:start_date2, 'YYYY/MM/DD'))
                               AND GREATEST(TO_DATE(:end_date1, 'YYYY/MM/DD'), TO_DATE(:end_date2, 'YYYY/MM/DD'))
       ) c;