【问题标题】:Populating a time dimension table automatically自动填充时间维度表
【发布时间】:2012-03-06 12:18:26
【问题描述】:

我目前正在处理一个报告项目。在我的数据仓库中,我需要一个维度表“时间”,其中包含所有日期(可能是从 01-01-2011 开始?),并且每天自动递增,格式为 yyyy-mm-dd。 顺便说一句,我在 Debian 上使用 MySQL。 谢谢 JT

【问题讨论】:

标签: mysql sql database debian data-warehouse


【解决方案1】:

您可以添加DATE 字段并使用这样的查询 -

INSERT INTO table(date_column, column1, column2)
  VALUES(DATE(NOW()), 'value1', 'value2');

另外,您可以使用 ON UPDATE CURRENT_TIMESTAMP 添加 TIMESTAMP 列,在这种情况下,日期时间值将自动更新。

Automatic Initialization and Updating for TIMESTAMP

【讨论】:

    【解决方案2】:

    See this answer

    Or This one

    那里有很多建议。如果您的日期范围适中,可能是一两年,并且假设您的报告使用存储过程来返回结果,您可以使用带限制的 rownum 技术动态创建一个临时表,以获取所有信息范围内的日期。然后根据需要加入您的数据。

    如果根据 cmets,第二个答案中的 Union 技巧似乎表现良好,并且可以扩展到您需要的任何最大范围。虽然很乱!

    【讨论】:

    • 是的,其实我真正需要的不会超过十二个月左右。我考虑过使用插入 CURDATE() 的简单脚本并在 crontab 中安排执行,但我对后者不是很熟悉。
    • @JıhadV.Tawfiq - 您不需要存储日期。只需创建一个永久表,其中包含一个名为 num 的单个 int 列,其值为 1,2,3....365(或您可能需要的任何数字)。然后SELECT DATE_ADD(NOW(), INTERVAL -1*num DAY) AS Dates FROM NewNumberTable WHERE num < 365将此用作子查询并将其连接到报告的剩余数据中。每次运行查询时,它都会为您提供最近的 365 个日期,无论您何时运行。
    • @Tobsey 为什么不存储日期?存储很简单,查询更容易,报告工具可以向用户呈现真实日期。
    • @Pondlife - 是的,我可能会同意。我会创建一个表格,其中包含我可能需要的过去和未来的日期,然后在所需的日期范围内对其进行过滤。无需每天为其添加日期。
    【解决方案3】:

    这个article 似乎涵盖了您想要的内容。另请参阅this question 以获取您可能希望在表中包含的列的另一个示例。您绝对应该提前生成大量日期,而不是每天更新表格;它节省了大量的工作和复杂性。 100 年只有 ~36500 行,这是一张小桌子。

    临时表或程序代码不是数据仓库的好解决方案,因为您希望您的报告工具能够访问维度表。如果您的 RDBMS 对星型模式查询进行了优化(我不知道 MySQL 是否这样做),那么它也需要查看维度。

    【讨论】:

      【解决方案4】:

      这是我用来创建和填充时间维度表的内容:

      DROP TABLE IF EXISTS time_dimension;
      CREATE TABLE time_dimension (
              id                      INTEGER PRIMARY KEY,  -- year*10000+month*100+day
              db_date                 DATE NOT NULL,
              year                    INTEGER NOT NULL,
              month                   INTEGER NOT NULL, -- 1 to 12
              day                     INTEGER NOT NULL, -- 1 to 31
              quarter                 INTEGER NOT NULL, -- 1 to 4
              week                    INTEGER NOT NULL, -- 1 to 52/53
              day_name                VARCHAR(9) NOT NULL, -- 'Monday', 'Tuesday'...
              month_name              VARCHAR(9) NOT NULL, -- 'January', 'February'...
              holiday_flag            CHAR(1) DEFAULT 'f' CHECK (holiday_flag in ('t', 'f')),
              weekend_flag            CHAR(1) DEFAULT 'f' CHECK (weekday_flag in ('t', 'f')),
              UNIQUE td_ymd_idx (year,month,day),
              UNIQUE td_dbdate_idx (db_date)
      
      ) Engine=MyISAM;
      
      DROP PROCEDURE IF EXISTS fill_date_dimension;
      DELIMITER //
      CREATE PROCEDURE fill_date_dimension(IN startdate DATE,IN stopdate DATE)
      BEGIN
          DECLARE currentdate DATE;
          SET currentdate = startdate;
          WHILE currentdate <= stopdate DO
              INSERT INTO time_dimension VALUES (
                  YEAR(currentdate)*10000+MONTH(currentdate)*100 + DAY(currentdate),
                  currentdate,
                  YEAR(currentdate),
                  MONTH(currentdate),
                  DAY(currentdate),
                  QUARTER(currentdate),
                  WEEKOFYEAR(currentdate),
                  DATE_FORMAT(currentdate,'%W'),
                  DATE_FORMAT(currentdate,'%M'),
                  'f',
                  CASE DAYOFWEEK(currentdate) WHEN 1 THEN 't' WHEN 7 then 't' ELSE 'f' END
                  );
              SET currentdate = ADDDATE(currentdate,INTERVAL 1 DAY);
          END WHILE;
      END
      //
      DELIMITER ;
      
      TRUNCATE TABLE time_dimension;
      CALL fill_date_dimension('1800-01-01','2050-01-01');
      OPTIMIZE TABLE time_dimension;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-08-07
        • 2020-11-07
        • 1970-01-01
        • 1970-01-01
        • 2013-12-01
        • 2013-03-19
        • 2012-04-02
        • 1970-01-01
        相关资源
        最近更新 更多