2011-04-30 2 views
4

Nous sommes en train de créer une archive historique pour une base de données d'historique du monde et nous avons besoin d'une table de recherche de dates qui référence toutes les dates dans AD. Comment créer les valeurs pour cette table - de 1AD à 2011 comme AAAA/MM/JJ? La base de données est MySQL.Entrepôt de données pour les dates AD

Problèmes:

  1. J'utilise Excel pour pré-remplir les dates, puis les importer dans MySQL comme: JJ/MM/DD mais Excel ne reconnaît pas comme des années 0007, 0008, etc donc Je ne peux pas copier automatiquement les cellules pour générer des dates. Je dois le faire manuellement et cela prendra des jours pour aller de 1AD à l'année 2011 comme AAAA/MM/DD.

  2. Les années bissextiles ont été introduites en 1752. Si je génère par programme des dates, comment puis-je gérer les cas antérieurs à 1752 sans années bissextiles? Cela va générer de mauvaises dates.

Ma table:

CREATE TABLE `dates` (
     `date_id` int(10) NOT NULL, 
     `format` char(10) NOT NULL, 
     `century` int(10) NOT NULL, 
     `decade` int(10) NOT NULL, 
     `year` int(10) NOT NULL, 
     `month` int(10) NOT NULL, 
     `week` int(10) NOT NULL, 
     `day` int(10) NOT NULL, 
     `month_year` int(10) NOT NULL, 
     `week_year` int(10) NOT NULL, 
     `week_month` int(10) NOT NULL, 
     `day_year` int(10) NOT NULL, 
     `day_month` int(10) NOT NULL, 
     `day_week` int(10) NOT NULL, 
     PRIMARY KEY (`date_id`) 
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 
+1

Pourquoi une 'DateTime' normale type colonne insuffisante? Y a-t-il des événements qui ont plusieurs dates ou plages de dates? –

+0

Oui, il s'agit d'une base de données de l'histoire du monde en profondeur pour l'analyse. Pensez à n'importe quel événement comme une guerre mondiale, une révolution, etc. Il s'agit de plusieurs jours, semaines, mois, années, etc. De plus, nous avons des croyances historiques comme les gens croyaient aux sorcières jusqu'au 19-20ème siècle, cela s'étend sur des milliers de années. – yardy

+1

Même pour les plages de dates, tout ce dont vous avez besoin est de deux colonnes 'datetime' (début/fin) ... Votre approche me semble toujours drôle. Pouvez-vous justifier pourquoi les colonnes 'datetime' sont insuffisantes? Le pire dans tout cela est que chaque jour vous avez besoin d'un nouvel enregistrement dans votre table 'dates' ... vous devrez générer des dates dans le futur à travers, disons, 9999AD. Et pire encore, la plupart de cette table serait pleine de données en double (siècle, par exemple, est généralement inutile - vous pouvez le déterminer à l'exécution, pas besoin d'une ligne de base de données pour vous dire cela). –

Répondre

7

Utilisez quelque chose comme ça SQL (en utilisant ma propre structure de la table, pas celui que vous aviez bien):

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')), 
     event     VARCHAR(50), 
     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, 
         NULL); 
     SET currentdate = ADDDATE(currentdate,INTERVAL 1 DAY); 
    END WHILE; 
END 
// 
DELIMITER ; 

TRUNCATE TABLE time_dimension; 

CALL fill_date_dimension('1-01-01','2015-01-01'); 
OPTIMIZE TABLE time_dimension; 
+0

Beautiful!J'ai résolu mon problème, sinon je devrais passer 2-3 jours à travailler dur en tapant toutes les dates. Merci. – yardy

Questions connexes