在SQL中计算日期范围中的特定日期

时间:2017-01-09 12:24:50

标签: sql oracle count date-range

我想问你如何从Oracle SQL的日期范围(DD-MON-YY)中获取特定日期(DD-MON)的计数? 这就是我所拥有的:

<head>

我想从日期范围INSTALL_D和SYSDATE计算DOB。让我们说

  1. 18-NOV的行出现5次,
  2. 13-JUN的行显示5次,
  3. 带有12-AUG的
  4. 行出现5次,
  5. 24-OCT的行是5次
  6. 最后一次只有4次。

    所以,结果应该是:

    MEMBERS    INSTALL_D   DOB      SYSDATE
    6934109    22-FEB-12   18-NOV   09-JAN-17
    6934109    22-FEB-12   13-JUN   09-JAN-17
    6934109    22-FEB-12   12-AUG   09-JAN-17
    6934109    22-FEB-12   24-OCT   09-JAN-17
    6934109    22-FEB-12   04-FEB   09-JAN-17
    

    我尝试过使用MONTHS_BETWEEN功能,但这不是我想要的。

    编辑:
    我会更具体。我使用此查询获取上面的第一个表:
    MEMBERS INSTALL_D DOB SYSDATE COUNT(DOB) 6934109 22-FEB-12 18-NOV 09-JAN-17 5 6934109 22-FEB-12 13-JUN 09-JAN-17 5 6934109 22-FEB-12 12-AUG 09-JAN-17 5 6934109 22-FEB-12 24-OCT 09-JAN-17 5 6934109 22-FEB-12 04-FEB 09-JAN-17 4

    select B0022HOME_NO as Members, B0022INSTALLDATE as INSTALL_DATE, to_char(to_date (encryption.decrypt(a.B0031MEMDATEOFBIRT),'DD-MON-YYYY'),'DD-MON')as DOB, SYSDATE from BT0022, BT0031 a where B0022HOME_NO=a.B003101HOME_NO and BT0022.B0022HOME_NO=6934109;是安装日,在此示例中为22-FEB-12
    INSTALL_D是会员的生日。只有日和月(DD-MON)
    DOB是实际日期。

    让我们说,如果sysdate为18-NOV-12且INSTALL_D为22-FEB-12且成员的DOB为18-NOV,则表示DOB发生一次这个日期范围。
    在示例中:INSTALL_D 22-FEB-12和SYSDATE 09-JAN-17是18-NOV的DOB发生5次,但如果SYSDATE将是18-NOV-17,则将是6次。这就是我在日期范围内向你询问的关于计数(DOB)的内容。

    提前致谢

3 个答案:

答案 0 :(得分:1)

这是希望与闰年发生的dob一起工作的另一种方式:

(Nb我假设您的所有日期都存储为DATE,这意味着您的dob列有多年。如果不是这样的话,那么a)为什么你不用dob存储年份? b)您必须更新我的查询以将字符串转换为适合比较的格式。

WITH sample_data AS (SELECT 6934109 members, to_date('22/02/2012', 'dd/mm/yyyy') install_d, to_date('18/11/1969', 'dd/mm/yyyy') dob FROM dual UNION ALL
                     SELECT 6934109 members, to_date('22/02/2012', 'dd/mm/yyyy') install_d, to_date('13/06/1991', 'dd/mm/yyyy') dob FROM dual UNION ALL
                     SELECT 6934109 members, to_date('22/02/2012', 'dd/mm/yyyy') install_d, to_date('12/08/1982', 'dd/mm/yyyy') dob FROM dual UNION ALL
                     SELECT 6934109 members, to_date('22/02/2012', 'dd/mm/yyyy') install_d, to_date('24/10/1963', 'dd/mm/yyyy') dob FROM dual UNION ALL
                     SELECT 6934109 members, to_date('22/02/2012', 'dd/mm/yyyy') install_d, to_date('04/02/1975', 'dd/mm/yyyy') dob FROM dual UNION ALL
                     SELECT 6934110 members, to_date('28/02/2011', 'dd/mm/yyyy') install_d, to_date('29/02/1976', 'dd/mm/yyyy') dob FROM dual UNION ALL
                     SELECT 6934110 members, to_date('29/02/2012', 'dd/mm/yyyy') install_d, to_date('01/03/1975', 'dd/mm/yyyy') dob FROM dual UNION ALL
                     SELECT 6934111 members, to_date('01/01/2017', 'dd/mm/yyyy') install_d, to_date('12/01/1957', 'dd/mm/yyyy') dob FROM dual UNION ALL
                     SELECT 6934111 members, to_date('01/01/2017', 'dd/mm/yyyy') install_d, to_date('02/01/1980', 'dd/mm/yyyy') dob FROM dual UNION ALL
                     SELECT 6934112 members, to_date('01/03/2011', 'dd/mm/yyyy') install_d, to_date('29/02/1976', 'dd/mm/yyyy') dob FROM dual UNION ALL
                     SELECT 6934112 members, to_date('29/02/2012', 'dd/mm/yyyy') install_d, to_date('29/02/1976', 'dd/mm/yyyy') dob FROM dual)
SELECT members,
       install_d,
       dob,
       SYSDATE,
       date_of_first_year,
       date_of_latest_year,
       months_between(date_of_latest_year, date_of_first_year)/12 + 1 count_birthdays
FROM   (SELECT members,
               install_d,
               dob,
               SYSDATE,
               CASE WHEN to_char(dob, 'mmdd') < to_char(install_d, 'mmdd') THEN
                         trunc(add_months(install_d, 12), 'yyyy')
                    ELSE trunc(install_d, 'yyyy')
               END date_of_first_year,
               CASE WHEN to_char(dob, 'mmdd') <= to_char(SYSDATE, 'mmdd') THEN
                         trunc(SYSDATE, 'yyyy')
                    ELSE add_months(trunc(SYSDATE, 'yyyy'), -12)
               END date_of_latest_year
        FROM   sample_data);

   MEMBERS INSTALL_D   DOB         SYSDATE     DATE_OF_FIRST_YEAR DATE_OF_LATEST_YEAR COUNT_BIRTHDAYS
---------- ----------- ----------- ----------- ------------------ ------------------- ---------------
   6934109 22/02/2012  18/11/1969  09/01/2017  01/01/2012         01/01/2016                        5
   6934109 22/02/2012  13/06/1991  09/01/2017  01/01/2012         01/01/2016                        5
   6934109 22/02/2012  12/08/1982  09/01/2017  01/01/2012         01/01/2016                        5
   6934109 22/02/2012  24/10/1963  09/01/2017  01/01/2012         01/01/2016                        5
   6934109 22/02/2012  04/02/1975  09/01/2017  01/01/2013         01/01/2016                        4
   6934110 28/02/2011  29/02/1976  09/01/2017  01/01/2011         01/01/2016                        6
   6934110 29/02/2012  01/03/1975  09/01/2017  01/01/2012         01/01/2016                        5
   6934111 01/01/2017  12/01/1957  09/01/2017  01/01/2017         01/01/2016                        0
   6934111 01/01/2017  02/01/1980  09/01/2017  01/01/2017         01/01/2017                        1
   6934112 01/03/2011  29/02/1976  09/01/2017  01/01/2012         01/01/2016                        5
   6934112 29/02/2012  29/02/1976  09/01/2017  01/01/2012         01/01/2016                        5

如果你想要2月29日的一部分与非闰年的3月1日相匹配,那就是美中不足。

我上面的查询中没有该逻辑,但您可以随时添加一个检查来比较install_d和sysdate年份的二月的最后一天,如果它是28,那么就更改一个&#39; 29/02&#39;到&#39; 01/03&#39;在做那个比较之前。 (即比较install_d的29/02/2012与dob = 29/02,因为2012年是闰年。你不需要比较sysdate,因为0301&gt; = 0229和0228&lt; 0229,是否是对sysdate是否是闰年。)

答案 1 :(得分:0)

You could group by date segments, it's not the prettiest thing but will work. e.g.

GROUP BY CAST(DATEPART(mm, dob) AS VARCHAR(2)) + '-' + CAST(DATEPART(yyyy, dob) AS VARCHAR(4))

you could also place that in the select statement

答案 2 :(得分:0)

试试这个:(分组应该工作)

SELECT MEMBERS,INSTALL_D,DOB,SYSDATE,Count(DOB) FROM table_name GROUP BY  DOB ,MEMBERS,INSTALL_D  ,SYSDATE