繁体   English   中英

如果我将360个月添加到begin_date,如何使用查找维表准确获取end_date?

[英]If I add 360 months to begin_date, How can I accurately obtain end_date using a lookup dimension table?

编辑:begin_date和end_date是任何表中的DATE列类型。

我有以下维度表,该表提供了1980年到2500年之间每个月的总天数:

CREATE TABLE total_days
    (
from_date     DATE,
to_date       DATE,
days_in_month SMALLINT
    );

from_date   to_date     days_in_month
1980-01-01  1980-01-31  31
1980-02-01  1980-02-29  29
...
2500-11-01  2500-11-30  30
2500-12-01  2500-12-31  31

如果要向begin_date添加360个月,如何构造SQL查询以获得准确的end_date ?.是否需要以任何方式更改维度表以实现目标?

编辑:必须在不使用任何本机SQL日期算术函数的情况下执行日期算术。 必须通过在尺寸表中查找begin_date来完成。

我想您有您的原因-这是一个非常简单的技巧- 假设事实表每个月都有一行-添加代表monthnumber的新列,将其从1开始并按时间顺序自动递增, 而不是从头开始每年。

SELECT B.* 
FROM SO_total_days2 A
INNER JOIN SO_total_days2 B ON B.monthnumber = A.monthnumber + 360
WHERE A.from_date =  '2010-01-01'

from_date   to_date     days_in_month monthnumber
1980-01-01  1980-01-31  31    1
1980-02-01  1980-02-29  29    2
1980-03-03  1980-03-31  31    3
...
1981-01-01  1981-01-31  31    13
1981-12-01  1981-12-31  31    24
...
1985-01-01  1985-01-31  31    49
1985-12-01  1985-12-31  31    60

这就是我想象的“事实表”如下所示:

declare @dt datetime
    set @dt = '7-1-2012'

;
with date_table as  (
        select  @dt as [Start Date],
                dateadd(d,-1,dateadd(mm,1,@dt)) as [End Date],
                datepart(d,dateadd(d,-1,dateadd(mm,1,@dt))) as [Days]

        union ALL

        select  dateadd(mm, 1, [Start Date]) as  [Start Date],
                dateadd(d,-1,dateadd(mm,1,dateadd(mm, 1, [Start Date]))) as [End Date], 
                datepart(d,dateadd(d,-1,dateadd(mm,1,dateadd(mm, 1, [Start Date])))) as [Days]

        from    date_table
        where   dateadd(mm, 1, [Start Date]) <= dateadd(m,500,@dt))

select  [Start Date], [End Date], [Days]
into    #temp
from    date_table

option (MAXRECURSION 0)

这是选择日期。 (请注意,这些语句中不包含DATEADD或DATEPART)

select  finish.[Start Date], finish.[End Date], finish.[Days]
from    (select rownum
         from   (select [Start Date], [End Date], [Days], row_number() over (order by [Start Date]) as rownum
                    from    #temp) as x
         where  x.[Start Date] = '2012-07-01 00:00:00.000' ) as start 

        join    (select [Start Date], [End Date], [Days], 
                        row_number() over (order by [Start Date]) as rownum
                 from   #temp) as finish
            on finish.rownum = start.rownum + 360

我在下面阅读了您的评论...如果您要总结这些天或某事,这是您可以做到的:(因此,从2012年7月1日开始,持续360个月... date_diff_days结果将是360个月的总天数...使用我制作的#temp表...我认为与您的事实表类似...我有10957天)

select  sum(dayscount.[Days]) as date_diff_days
from    (select rownum
         from   (select [Start Date], [End Date], [Days], row_number() over (order by [Start Date]) as rownum
                    from    #temp) as x
         where  x.[Start Date] = '2012-07-01 00:00:00.000' ) as start 

        join    (select [Start Date], [End Date], [Days], 
                        row_number() over (order by [Start Date]) as rownum
                 from   #temp) as finish
            on finish.rownum = start.rownum + 360

        join (select    [Start Date], [End Date], [Days], 
                        row_number() over (order by [Start Date]) as rownum
                 from   #temp) as dayscount
            on dayscount.rownum >= start.rownum and 
                dayscount.rownum < finish.rownum 

如果我想以不可知论的方式来做数据库,那么我会稍微修改事实表:

CREATE TABLE total_days
(
  year          INT,
  month         TINYINT,
  from_date     DATE,
  to_date       DATE,
  days_in_month SMALLINT
);

year  month  from_date   to_date     days_in_month
------------------------------------------------
1980    1    1980-01-01  1980-01-31   31
1980    2    1980-02-01  1980-02-29   29
...
2500   11    2500-11-01  2500-11-30   30
2500   12    2500-12-01  2500-12-31   31

然后,您可以使用类似:

SELECT td.* 
FROM 
      total_days AS td 
   CROSS JOIN
      ( SELECT year, month
        FROM total_days 
        WHERE from_date <= @StartingDate 
          AND @StartingDate <= to_date
      ) AS st
   CROSS JOIN
      ( SELECT 360 AS add_months ) AS param
WHERE td.year = st.year + ( st.month -1 + add_months ) / 12
  AND td.month = 1 + ( st.month - 1 + add_months ) % 12 )
;

或更简单(但为效率进行优化则有点困难:

WHERE 12 * td.year + td.month = 
      12 * st.year + st.month + add_months

为什么是事实表? 大多数数据库都对日期/时间操作具有本地支持。 在MS SQL Server中,您可以使用DATEADD进行此操作。

我看到您用“ informix”标记了您的问题,但未在问题中指定任何版本详细信息。 这是IBM Informix 11.50中的ADD_MONTHS函数。

您可以使用间隔

mysql> SELECT '2008-12-31 23:59:59' + INTERVAL 1 month;
+------------------------------------------+
| '2008-12-31 23:59:59' + INTERVAL 1 month |
+------------------------------------------+
| 2009-01-31 23:59:59                      |
+------------------------------------------+
1 row in set (0.00 sec)


mysql> select now();
+---------------------+
| now()               |
+---------------------+
| 2012-07-03 12:27:46 |
+---------------------+
1 row in set (0.00 sec)

mysql> SELECT now() + INTERVAL 30 month;
+---------------------------+
| now() + INTERVAL 30 month |
+---------------------------+
| 2015-01-03 12:27:49       |
+---------------------------+
1 row in set (0.00 sec)

编辑:

mysql> SELECT STR_TO_DATE('01,5,2013','%d,%m,%Y') + interval 30 month;
+---------------------------------------------------------+
| STR_TO_DATE('01,5,2013','%d,%m,%Y') + interval 30 month |
+---------------------------------------------------------+
| 2015-11-01                                              |
+---------------------------------------------------------+
1 row in set (0.00 sec)

编辑2:

mysql> show create table tiempo;
+--------+------------------------------------------------------------------------------------------------+
| Table  | Create Table                                                                                   |
+--------+------------------------------------------------------------------------------------------------+
| tiempo | CREATE TABLE `tiempo` (
  `fecha` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+--------+------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select fecha + interval 20 month from tiempo;
+---------------------------+
| fecha + interval 20 month |
+---------------------------+
| NULL                      |
| 2001-10-02 02:02:02       |
+---------------------------+
2 rows in set (0.00 sec)

如果您的起始日期与列出的日期完全相同,并且您始终要添加月份,则可以使用以下方法:

SELECT max (to_date)
  FROM (SELECT ROW_NUMBER () OVER (ORDER BY from_date) AS Row,
                from_date,
                to_date,
                days_in_month
         FROM total_days
        WHERE from_date > '1/1/1982'
      GROUP BY from_date, to_date, days_in_month) MyDates
 WHERE Row <= 360

暂无
暂无

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

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