【问题标题】:How to get monthly counts between two Date IDs in Oracle如何在 Oracle 中的两个日期 ID 之间获取每月计数
【发布时间】:2020-01-07 17:38:07
【问题描述】:

我想获取两个日期范围之间的每月计数。例如,让我们采用以下范围:

20181202 - 20190202

此范围将为 2018 年的“十二月”和 2019 年的“一月”、“二月”的计数提供 +1。

目前我按月和年汇总以获得这些计数,但我忘记了日期之间存在超过 1 年差距的情况。

查询现在看起来像这样:

    CREATE VIEW V_A_A AS
SELECT CASE WHEN 01>=JT.SUBSTR(START,5,2) AND 01<=JT.SUBSTR(ENDID,1,4) THEN 'JAN'
WHEN 02>=JT.SUBSTR(START,5,2) AND 02<=JT.SUBSTR(ENDID,5,2) THEN 'FEB'
WHEN 03>=JT.SUBSTR(START,5,2) AND 03<=JT.SUBSTR(ENDID,5,2) THEN 'MAR'
WHEN 04>=JT.SUBSTR(START,5,2) AND 04<=JT.SUBSTR(ENDID,5,2) THEN 'APR'
WHEN 05>=JT.SUBSTR(START,5,2) AND 05<=JT.SUBSTR(ENDID,5,2) THEN 'MAY'
WHEN 06>=JT.SUBSTR(START,5,2) AND 06<=JT.SUBSTR(ENDID,5,2) THEN 'JUNE'
WHEN 07>=JT.SUBSTR(START,5,2) AND 07<=JT.SUBSTR(ENDID,5,2) THEN 'JULY'
WHEN 08>=JT.SUBSTR(START,5,2) AND 08<=JT.SUBSTR(ENDID,5,2) THEN 'AUG'
WHEN 09>=JT.SUBSTR(START,5,2) AND 09<=JT.SUBSTR(ENDID,5,2) THEN 'SEPT'
WHEN 10>=JT.SUBSTR(START,5,2) AND 10<=JT.SUBSTR(ENDID,5,2) THEN 'OCT'
WHEN 11>=JT.SUBSTR(START,5,2) AND 11<=JT.SUBSTR(ENDID,5,2) THEN 'NOV'
WHEN 12>=JT.SUBSTR(START,5,2) AND 12<=JT.SUBSTR(ENDID,5,2) THEN 'DEC' ELSE 'N/A' END MONTH
,CASE WHEN 2019>=JT.SUBSTR(START,1,4) AND 2019<=JT.SUBSTR(ENDID,1,4) THEN 2019 
WHEN 2018>=JT.SUBSTR(START,1,4) AND 2018<=JT.SUBSTR(ENDID,1,4) THEN 2018
WHEN 2017>=JT.SUBSTR(START,1,4) AND 2017<=JT.SUBSTR(ENDID,1,4) THEN 2017
WHEN 2016>=JT.SUBSTR(START,1,4) AND 2016<=JT.SUBSTR(ENDID,1,4) THEN 2016
WHEN 2015>=JT.SUBSTR(START,1,4) AND 2015<=JT.SUBSTR(ENDID,1,4) THEN 2015 ELSE 0 END YEAR
,COUNT(*) AS COUNT
from 
(select * from some_db a
INNER JOIN another_db b ON a.field = b.field
WHERE a.name = "Private" JT 
GROUP BY CASE WHEN 2019>=JT.SUBSTR(START,1,4) AND 2019<=JT.SUBSTR(ENDID,1,4) THEN 2019 
WHEN 2018>=JT.SUBSTR(START,1,4) AND 2018<=JT.SUBSTR(ENDID,1,4) THEN 2018
WHEN 2017>=JT.SUBSTR(START,1,4) AND 2017<=JT.SUBSTR(ENDID,1,4) THEN 2017
WHEN 2016>=JT.SUBSTR(START,1,4) AND 2016<=JT.SUBSTR(ENDID,1,4) THEN 2016
WHEN 2015>=JT.SUBSTR(START,1,4) AND 2015<=JT.SUBSTR(ENDID,1,4) THEN 2015 ELSE 0 END,
CASE WHEN 01>=JT.SUBSTR(START,5,2) AND 01<=JT.SUBSTR(ENDID,1,4) THEN 'JAN'
WHEN 02>=JT.SUBSTR(START,5,2) AND 02<=JT.SUBSTR(ENDID,5,2) THEN 'FEB'
WHEN 03>=JT.SUBSTR(START,5,2) AND 03<=JT.SUBSTR(ENDID,5,2) THEN 'MAR'
WHEN 04>=JT.SUBSTR(START,5,2) AND 04<=JT.SUBSTR(ENDID,5,2) THEN 'APR'
WHEN 05>=JT.SUBSTR(START,5,2) AND 05<=JT.SUBSTR(ENDID,5,2) THEN 'MAY'
WHEN 06>=JT.SUBSTR(START,5,2) AND 06<=JT.SUBSTR(ENDID,5,2) THEN 'JUNE'
WHEN 07>=JT.SUBSTR(START,5,2) AND 07<=JT.SUBSTR(ENDID,5,2) THEN 'JULY'
WHEN 08>=JT.SUBSTR(START,5,2) AND 08<=JT.SUBSTR(ENDID,5,2) THEN 'AUG'
WHEN 09>=JT.SUBSTR(START,5,2) AND 09<=JT.SUBSTR(ENDID,5,2) THEN 'SEPT'
WHEN 10>=JT.SUBSTR(START,5,2) AND 10<=JT.SUBSTR(ENDID,5,2) THEN 'OCT'
WHEN 11>=JT.SUBSTR(START,5,2) AND 11<=JT.SUBSTR(ENDID,5,2) THEN 'NOV'
WHEN 12>=JT.SUBSTR(START,5,2) AND 12<=JT.SUBSTR(ENDID,5,2) THEN 'DEC' ELSE 'N/A' END

【问题讨论】:

  • 您的startendid 列是哪种数据类型?里面存储了哪些值?举个例子。
  • 它们是数字数据类型,示例见上图(20181202, 20190202)
  • 您是否要获取两个日期之间的月数(包括开始和结束月份)?例如。你想从样本输入中得到 3 ..?或列出所有月份,例如 2018DEC - 2019JAN - 2019FEB ?
  • @BarbarosÖzhan 我希望视图产生一个结果,其中年份是一列,月份是一列,计数是一列。包括开始和结束月份!因此,在包含 2018 年的行中,12 月在这种情况下应该计数为 1(所有其他有效月份也应该计数为 1)。

标签: sql oracle


【解决方案1】:

据我了解,您需要整年的边界日期(在这种情况下为 2018 - 2019 年)。所以应该有24行。如果这 24 个月与边界日期之间的间隔月重合,那么您需要计数为 1,否则为 0。所以,考虑一下:

SELECT SUBSTR(t1.months,1,4) as "Year", 
       TO_CHAR( TO_DATE(t1.months,'yyyymm'), 'Month' ) as "Month",
       NVL2(t2.months,1,0) as "Count"
  FROM
  (
SELECT y.years||m.months as months
  FROM
  (
   SELECT DISTINCT TO_CHAR(ADD_MONTHS( TO_DATE('20181202','yyyymmdd') , level - 1 ),'yyyy')
          as years
     FROM dual
  CONNECT BY level <= 
    MONTHS_BETWEEN(TO_DATE('20190202','yyyymmdd'),TO_DATE('20181202','yyyymmdd')) + 1 ) y
   CROSS JOIN
   (
    SELECT LPAD(LEVEL,2,'0') months
      FROM dual
   CONNECT BY level <= 12
   ) m
  ) t1
 LEFT JOIN
 (
    SELECT TO_CHAR(ADD_MONTHS( TO_DATE('20181202','yyyymmdd') , level - 1 ),'yyyymm')
          as months
     FROM dual
  CONNECT BY level <= 
      MONTHS_BETWEEN(TO_DATE('20190202','yyyymmdd'),TO_DATE('20181202','yyyymmdd')) + 1
 ) t2
 ON t1.months = t2.months
 ORDER BY t1.months

CROSS JOIN 然后递归LEFT JOIN

Demo

【讨论】:

  • 你能简单解释一下你在这里做什么吗?正如我的用户名所暗示的,我对这些概念很陌生:/.
  • 我首先要问这是你想要的结果吗? @novice_programmer9623
  • 我在第一步中确定了边界日期所触及的所有年份和所有月份,然后通过 CROSS JOIN(例如 CARTESIAN PRODUCT)生成 #of years 乘以 12 个月并使用 LEFT JOIN 来保持所有行在第一步中生成行。在所有这一切中,我生成日期范围的年月对作为最右边的子查询,并通过来自最右边的子查询 @novice_programmer9623 的空值将它们的计数视为 0,这是 LEFT JOIN 机制的性质。
  • 谢谢,我是否可以在此查询中使用 START 和 ENDID 字段?我收到一条错误消息,当我用原来的联接替换您的 FROM 子句时找不到 START
  • 不客气@novice_programmer9623。 start 是保留关键字,不能作为列名,除非引用(“start”或“START”或“sTaRt”反之亦然......),您可以替换为startid 作为示例。顺便说一句,20181202 可能会在您的查询中替换为 '&amp;startid'20190202'&amp;endid' 替换变量。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-28
  • 2019-12-27
  • 2013-10-17
  • 2019-04-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多