Празненство!! Време за семейството!! Дълъг път!! Един ден на плажа!! Всички тези думи се появяват в съзнанието ни, когато мислим за празници. Замисляли ли сте се как една мултинационална компания следи празниците по целия свят? Трябва да има речник с данни, който да поддържа всички тези подробности, така че да могат да осигурят безпроблемен бизнес с местните си партньори.
Тази статия ще обясни такъв модел на данни.
Изисквания на проекта накратко
Този път имам доста прости и ясни изисквания. Трябва да създам речник с данни за празници в много страни. Искам да го изградя като компонент, който може да бъде интегриран в основния модел на данни, когато и където е необходимо.
За някои интересни факти за празниците в различни страни
По отношение на изискванията на проекта, това е един от най-простите проблеми при моделирането на данни. И все пак е достатъчно трудно да се проектира модел на данни за него. Обикновено празниците падат на определена дата всяка година, но това не е така за всеки празник във всяка страна. Ако анализираме празниците в различни страни, можем лесно да предвидим усложненията, свързани с този дизайн на модела на данни.
Нека да разгледаме някои интересни факти за празниците в различни страни:
-
Много празници, особено патриотични, се отбелязват на определена дата всяка година.
Пример:
Денят на независимостта в САЩ и Индия се чества съответно на 4 юли и 15 август.
-
Някои празници се празнуват на определен ден всяка година – но не винаги на една и съща календарна дата.
Пример:
Денят на благодарността в САЩ се празнува на 4 четвъртък на ноември. Миналата година (2015 г.) това падна на 26 ноември; тази година ще бъде 24 ноември.
-
Някои празници се празнуват на определена дата в годината, но ако датата пада в събота или неделя, празникът нарочно се измества към следващия понеделник, за да се спазва дълъг уикенд. Такъв празник понякога се нарича „Понеделник“ .
Примери:
В Австралия и Нова Зеландия денят на ANZAC се празнува на 6 февруари, но ако тази дата падне в събота или неделя, празникът се отбелязва в понеделник ден или два по-късно.
Друг добър пример е Денят на труда в Китай. Този празник също е „понеделник“.
-
Датите на някои празници се изместват със седмица, ако се сблъскват с друг празник.
Пример:
Денят на семейството и общността в Австралия се празнува в първия понеделник на октомври, но ако Денят на труда се пада и на първия понеделник, тогава Денят на семейството се измества към втория понеделник на октомври.
- Не всички празници се спазват като банкови празници т.е. празници, когато банките, финансовите институти, фондовите пазари и държавните служби са затворени. (В САЩ и Канада банковите празници са известни като федерални или законови празници.)
- Патриотичните празници се спазват стриктно на една и съща дата всяка година. В този ден са затворени всички институти и офиси (включително банки) във всички региони на страната. Въпреки това, в някои страни, като САЩ и Канада, ако тези празници попадат в уикенда, те ще се спазват и на следващия понеделник – тоест банките и държавните служби ще бъдат затворени в този понеделник.
-
Празниците с едно и също име се отбелязват в различни дни в различните страни.
Пример:
Денят на труда се отбелязва на 1 май в Индия, докато в Канада се отбелязва на първия понеделник на септември.
-
Някои празнични почивни дни традиционно се съчетават с непразнични дни.
Пример:
Денят на труда в Китай и Южна Африка се отбелязва в един ден, но са включени два други почивни дни.
-
Други дни, макар и технически да не са празници, обикновено се допускат като неработни дни.
Пример:
В САЩ петъкът след Деня на благодарността е неофициално известен като Черен петък. Това не е правителствен празник, но много компании дават на служителите си почивен ден.
-
Някои празници се наблюдават по различен начин в различните региони в рамките на една държава.
Пример:
Лятна банкова ваканция в Обединеното кралство се празнува в първия понеделник на август в Шотландия, но същият празник се отбелязва в последния понеделник на август в Англия, Гърнси, Джърси, Северна Ирландия и Уелс.
-
Определени регионални или местни празници се отбелязват само в една част на страната. Те може да са свързани с религиозни, етнически или културни събития.
Пример:
Денят на Луис Риел се празнува само в канадската провинция Манитоба.
-
Някои дни за спазване на определени празници се основават на условие „преди“ или „след“.
Примери:
- Денят на националния патриот се отбелязва в канадската провинция Квебек в понеделник преди 25 май.
- Денят на покаянието в Германия се отбелязва в сряда непосредствено преди 23 ноември.
- Jeune Genevois в Швейцария се наблюдава в четвъртък следващия първата неделя на септември.
-
Някои празнични дни се основават на по-стари календари, които не съответстват на често използвания григориански календар. Следователно датите им варират всяка година.
Примери:
- Великден се празнува в първата неделя след пълнолунието на или най-скоро след 21 март.
- Дивали (древен индуистки фестивал) се празнува в продължение на няколко дни, от края на индуисткия лунен месец Ашвин и началото на месец Картика. Обикновено това пада някъде между средата на октомври и средата на ноември според григорианския календар.
- Православна Коледа – Това следва по-стария юлиански календар. От 2016 г. има разлика от 13 дни между юлианския и григорианския календар. В резултат на това православната Коледа се пада на 7 януари 2016 г.
Обобщаване на фактите
Важно е да се отбележи, че Обмислям само международно приетия григориански календар (който следва слънчевия цикъл) за автоматизиране на популацията от данни за празници за години и държави. В тази статия Не обмислям лунно-слънчеви, еврейски или индуистки календари (които следват лунния цикъл). Въпреки това, тези календари се следват в определени региони на земното кълбо. Засега празниците въз основа на тези календари могат да се подават в системата ръчно .
За да обобщим, празниците в различните държави могат да бъдат категоризирани въз основа на това как са получени техните дати:
- Фиксирани празници – Празници, които се случват на определена дата всяка година.
- Преместваеми празници – Празници, които се падат в определен ден, като първия понеделник на февруари или третия четвъртък на ноември.
- Регулируеми празници – Празници, които попадат в някоя от категориите, но понякога се наблюдават в други дни, за да се избегне сблъсък с други празненства (или сблъсък с уикенда) или се преместват към следващата седмица поради сблъсък с друг празник на същата дата.
- Празници въз основа на други календари – Празнични празници, които се основават на лунния, православния или индуисткия календар. Засега те се подават ръчно в нашия модел.
Освен това можем да разделим празниците в две категории въз основа на къде те се наблюдават:
- Национални празници – Празници, които се спазват на ниво държава.
- Регионални или местни празници – Празници, които се отбелязват в определен щат или регион на дадена страна.
В почти всички страни националните и регионалните празници се отбелязват като празници на национално или регионално ниво. Не всички празници обаче са официални, така че трябва да посочим кои празници са официални и кои не.
На този етап трябва да разгледаме и някои теоретични сценарии за конкретни бизнес области. Например:
- В някои държави банките и други финансови институции получават почивен ден на първия ден от всяко тримесечие.
- Някои организации дават почивен ден, след като публикуват тримесечните си резултати.
Ще се уверим, че тези точки също са включени в дизайна на нашия модел на данни.
Проектиране на изчерпателен модел на ваканционни данни
Докато проектирам модела на данни, ще използвам конвенцията на САЩ, че седмицата започва в неделя. Няма да е трудно да промените това по-късно, ако е необходимо.
Целият този модел на данни ще се върти около три предметни области:„Календар“, „Празник“ и „Държава“.
Тематичната област „Календар“
В тази област има основна таблица с име calendar
който съхранява фурми в продължение на много години. Ще има и някои допълнителни колони за съхраняване на предварително изчислени числови стойности, които ще ни помогнат да изведем дати за определени подвижни празници. Колоните са както следва:
week_of_month
week_of_quarter
week_of_year
day_of_year
day_of_quarter
Има още две таблици в тази тематична област:day_of_week
и month_of_year
.
Както подсказват имената им, ние ще съхраняваме подробности за отделните дни и месеци в тези таблици. Следователно те винаги ще имат съответно 7 и 12 записа. Някои неща, които трябва да имате предвид за този раздел, са:
- Можем да конфигурираме началото на седмицата с помощта на колона за последователност в двете таблици. Можем да направим същото с началото на годината.
- Първичните ключове на двете таблици са посочени в
calendar
маса. Те съхраняват числови стойности за дните от седмицата и месеците от годината. - Стойността на годината може да бъде извлечена от
calendar_date
колона, но все още пазяcalendar_year
като отделна колона. Това ни позволява да разделим таблицата на тази колона, което от своя страна дава възможност за по-добра производителност за основните SQLs. - Размерът на числовите колони е определен въз основа на възможни стойности за колоната. Например
day_of_year
трябва да е някаква стойност между 1 и 365, така че дефинирам число(3) като тип данни на колоната.
Теманата област „Празник“
Както казахме преди, има два вида почивки – фиксирани и преместваеми. Така че ще създадем две различни таблици, по една за всеки тип.
holiday_fixed
таблицата използва day_of_month
и month_of_year_id
колони за съхраняване на числови стойности за ден и месец. Използвайки тези стойности, можем да извлечем дата за фиксиран празник.
На подобни линии, holiday_moveable
таблицата ще използва следните колони, за да изведе дата за всеки преместваем празник:
is_bank_holiday
колона показва дали празникът е празничен ден, т.е. всички финансови институции са затворени в този ден. Тази колона е задължителна и в двете таблици.
is_mondayized
колоната променя датата за празниците, които се падат в събота или неделя, но се спазват на следващия понеделник.
Нека също така създадем друга таблица, а именно holiday_miscellaneous
, за съхраняване на записи за празници въз основа на негригориански календари. Записите ще бъдат вмъкнати в тази таблица ръчно.
Всички тези три таблици имат една колона, препращаща holiday_category
маса. Това съдържа данни за естеството на празника. Тук може да има различни категории, включително:
- Обществен/банков празник – Банките са официално затворени и не се търгуват.
- Държавен празник – Официални празници само на държавно ниво.
- Национален празник – Обикновено патриотичен юбилей или ден, определен от закона, който се отбелязва в цялата страна.
- Местна почивка – Декларирано от местната власт и се наблюдава само в конкретен регион.
- Спазване – Празници, които не се празнуват на действителните си дати, а в някой друг ден (често понеделник). Обикновено позволява на хората да имат тридневен уикенд.
Сигурно сте забелязали state_id
колона и в трите празнични таблици. Нека поговорим за значението на тази колона в следващия раздел.
Предметната област „Държава“
Имаме две таблици в тази тематична област:
country
– който съхранява имена на държави и идентификационни номера;state
– който съхранява имената и идентификаторите на щати и/или региони за всяка отделна държава.
В крайна сметка ще се позоваваме на това state
таблица във всичките три празнични таблици, за да определите към кой регион, щат и държава принадлежи даден празник.
Тъй като много празници се празнуват на ниво държава, няма смисъл да се водят записи на държавно ниво за такива празници в holiday
маса. Това би станало изключително излишно. Вместо това можем да имаме един запис в state
таблица с „ВСИЧКИ“ като име на щат. Този запис може да бъде картографиран с всички празници на тази страна, като по този начин се елиминира необходимостта от водене на огромни записи в holiday
таблица ненужно.
Окончателният модел на данните за празниците
Нека да разгледаме пълния модел на данни за празниците тук:
Има няколко начина, по които можем да си играем с този модел. Например:
-
Вземете списък с всички празници, наблюдавани в определена страна, да речем Полша.
Select hm.holiday_name, calendar_date, hm.is_bank_holiday from calendar c, holiday_moveable hm Where hm.month_of_year_id = c.month_of_year_id and hm.day_of_week_id =c.day_of_week_id and c.calendar_year = 2016 And hm.state_id = (select state_id from state s, country c where s.country_id = c.id and c.country_name = ‘POLAND’ ) UNION ALL Select hf.holiday_name, calendar_date, hf.is_bank_holiday from calendar c, holiday_fixed hm Where hm.month_of_year_id = c.month_of_year_id and hm.day_of_month = to_number(to_char(c.calendar_date,’DD’)) and c.calendar_year = 2016 And hm.state_id = (select state_id from state s, country c where s.country_id = c.id and c.country_name = ‘POLAND’) ;
-
Намерете датата за Деня на благодарността през 2018 г. – Не забравяйте, че това се празнува във всички щати на САЩ в четвъртия четвъртък на ноември.
Select hm.holiday_name, calendar_date, hm.is_bank_holiday from calendar c, holiday_moveable hm Where hm.month_of_year_id = c.month_of_year_id And hm.day_of_week_id =c.day_of_week_id And c.calendar_year = 2018 And hm.holiday_name = ‘THANKSGIVING’ And hm.state_id = (select state_id from state s, country c where s.country_id = c.id and c.country_name = ‘USA’ )
-
Вземете списък с това кога се празнува Денят на независимостта във всички страни. Обикновено това е на определена дата всяка година и денят се спазва стриктно във всички райони на страната.
Select c.country_name, calendar_date from calendar c, holiday_fixed hf, state s, country c Where hf.state_id = s.id and s.country_id = c.id And s.state_name = ‘ALL’ And c.month_of_year_id = hf.month_of_year_id And c.day_of_month = trunc(calendar_date) And hf.holiday_name = ‘INDEPENDENCE DAY’ and c.calendar_year = 2016;
Използване на ваканционния модел на данни
Искате ли да поиграете с този модел на данни? Направи го. Ето само някои от запитванията, които измислихме:
- Намерете датите, на които се отбелязва Денят на труда в различни държави.
- Вземете списък с всички празници през 2016 г. за всяка част на Обединеното кралство.
- Направете списък на всички празници, наблюдавани във Франция през 2016 г.
- Вземете списъка с всички празници, наблюдавани в канадската провинция Манитоба през 2016 г.
Как успяхте да съхраните подробности за празниците в приложението си? Ще се радвам да чуя вашите идеи. Моля, не се колебайте да споделите опита си със съхраняването на тези метаданни, както и мнението си за нашето решение.