Przechowywanie godzin pracy w bazie danych

87

Obecnie próbuję znaleźć najlepszy sposób na przechowywanie godzin pracy firmy w bazie danych.

Na przykład:

Firma A ma następujące godziny pracy

  • Poniedziałek: 9:00 - 17:00
  • Wtorek: 9:00 - 17:00
  • Środa: 9:00 - 17:00
  • Czwartek: 9:00 - 17:00
  • Piątek: 9:00 - 17:00
  • Sobota: 9:00 - 12:00
  • Niedziela: zamknięte

Obecnie mam model danych podobny do następującego

CREATE TABLE "business_hours" (
    "id" integer NOT NULL PRIMARY KEY,
    "day" varchar(16) NOT NULL,
    "open_time" time,
    "close_time" time
)

gdzie „dzień” jest ograniczony do wyboru z 7 dni tygodnia w kodzie (poprzez ORM). Aby sprawdzić, czy firma jest zamknięta w określonym dniu, sprawdza, czy wartości open_time i close_time mają wartość NULL. Jest powiązany z biznesem poprzez tabelę pośrednią (relacja wiele do wielu).

Czy ktoś ma jakieś sugestie dotyczące tego schematu bazy danych? Coś w tym wydaje mi się nie w porządku.

user128000
źródło
4
Dlaczego potrzebujesz relacji M-to-M między tabelą godzin_biznesu a tabelą firm? Jeśli naprawdę chcesz, aby wiele firm korzystało z tego samego rekordu w godzinach pracy, dlaczego? Pod względem semantycznym fakt, że „firma C pracuje od T1 do T2 w dniu D” jest raczej obiektem wartości niż bytem ... Jedynym dobrym (?) Powodem, jaki mogę sobie wyobrazić, jest optymalizacja rozmiaru magazynu (wersja RDB wzorca Flyweight, by tak rzec), jeśli oczekuje się, że liczba biznesów będzie ogromna ...
Yarik
3
A co z przerwami obiadowymi? A co ze świętami?
Mawg mówi, że przywróć Monikę

Odpowiedzi:

58

Ogólnie nie widzę w tym nic złego. Z wyjątkiem...

  1. Zapisałbym dzień tygodnia jako liczbę całkowitą, używając dowolnego systemu numeracji, którego używa twój natywny język programowania (w jego bibliotekach). Spowoduje to zmniejszenie rozmiaru bazy danych i usunięcie porównań ciągów z kodu.

  2. Prawdopodobnie umieściłbym klucz obcy w tabeli biznesowej tutaj, w tej tabeli. W ten sposób nie będziesz potrzebować tabeli linków.

Więc myślę, że zrobiłbym:

CREATE TABLE "business_hours" (
     "id" integer NOT NULL PRIMARY KEY,
     "business_id" integer NOT NULL FOREIGN KEY REFERENCES "businesses",
     "day" integer NOT NULL,
     "open_time" time,
     "close_time" time
)

W mojej logice biznesowej narzuciłbym ograniczenie, aby każdy „biznes” miał co najmniej 7 „godzin pracy”. ( Przynajmniej dlatego, że Jon Skeet ma rację, możesz chcieć mieć dni wolne od pracy). Chociaż możesz chcieć złagodzić to ograniczenie, po prostu opuszczając „godziny pracy” w dni, w których firma jest zamknięta.

Frank Krueger
źródło
1
Jak byś zrobił 2? Masz wszystkie wpisy dla wszystkich firm, nawet jeśli dzień / godziny są takie same?
Vinko Vrsalovic
7
Powiedziałbym tak. W przeciwnym razie zastanów się, co by się stało, gdyby dwie firmy miały te same godziny, ale jedna z nich musiałaby zmienić swoje godziny. Musiałbyś wykryć fakt, że godziny uległy zmianie i albo utworzyć nowy rekord, albo edytować istniejący, w zależności od tego, czy jest udostępniany, czy nie.
Erik Forbes,
3
Absolutnie nie udostępniłbym wierszy tej tabeli firmom. Ten rodzaj dzielenia się prowadzi tylko do bólu. Logika biznesowa aplikacji powinna po prostu wymuszać ograniczenie, że każda firma ma co najmniej 7 odniesień „business_hours”.
Frank Krueger
1
@Vinko: Pamiętaj, że chociaż wartości są (obecnie) takie same, godziny otwarcia dwóch firm są semantycznie różne.
Draemon
1
Możesz także użyć 7 bitowej mapy bitowej dla „dnia”. Dzięki temu nie musisz powtarzać tych samych wpisów. Przykład wszystkie dni robocze mają te same godziny pracy, wystarczy jeden wpis.
ZolaKt
29

Jedna sytuacja, która nie jest objęta tym schematem, to kilka okresów otwarcia w ciągu dnia. Na przykład lokalny pub jest otwarty w godzinach 12: 00-14: 30 i 17: 00-23: 00.

Może kasa teatralna jest otwarta na popołudniowy i wieczorny spektakl.

W tym momencie musisz zdecydować, czy możesz mieć kilka wpisów w tym samym dniu, czy też chcesz przedstawić różne godziny w tym samym wierszu.

A co z godzinami otwarcia, które przekraczają północ? Powiedz, że bar jest otwarty 19: 00-02: 00. Nie można było po prostu porównać godzin otwarcia i zamknięcia z czasem, który chcesz przetestować.

davidsheldon
źródło
Skończyło się na tym, że zrobiłem coś takiego, jak zasugerował @JordanFeldstein. Przechowuję tablice „zmian stanu”, które obejmują zmianę (otwarcie lub zamknięcie), dzień tygodnia i porę dnia. Mogę wprowadzić tyle „zmian”, ile chcę dla każdej firmy i każdego dnia. Firma może być otwarta jednego dnia i zamknięta następnego, otwarta dwa razy (lub x razy) dziennie, może być otwarta 24 godziny, ale zamknięta w poniedziałki, cokolwiek. Jest trudny do wdrożenia, ale bardzo elastyczny.
ironcito,
Zgodnie z najlepszą odpowiedzią wolałbym dodać dwie kolumny do business_hours: break_timei break_duration. Naprawdę rzadko zdarza się mieć 2 przerwy tego samego dnia.
Frondor
13

To w pewnym sensie zależy od tego, w jakim celu chcesz je przechowywać i jak mogą wyglądać rzeczywiste dane.
Jeśli musisz być w stanie określić, czy firma jest otwarta w pewnym momencie, zapytanie o schemat może być nieco niewygodne. Ale co ważniejsze, brzmi: czy kiedykolwiek będziesz musiał przygotować się na zamknięcie w południe?

Niektóre opcje obejmują;

  • Schemat podobny do tego, który masz, ale z opcją wielu okresów w tym samym dniu. Zapewniłoby to przerwę na lunch, ale byłoby niewygodne uruchomienie zapytania, które podaje godziny otwarcia w danym dniu, np. W celu prezentacji użytkownikowi.
  • Podejście w stylu mapy bitowej; „000000000111111110000000” dla 9-5. Wadą tego podejścia jest to, że musisz wybrać konkretną szczegółowość, tj. Całe godziny lub pół godziny, a nawet minuty. Im drobniejsza ziarnistość, tym trudniejsze do odczytania dane dla człowieka. Możesz użyć operatorów bitowych, aby zapisać tę wartość jako pojedynczą liczbę, a nie jako ciąg liczb całkowitych, ale znowu szkodzi to czytelności.
Frans
źródło
11

Dowiedziałem się, że jeśli chcesz, aby znaczniki danych Google rozpoznawały Twoje dane, powinieneś przestrzegać następujących wskazówek:

https://schema.org/openingHours

http://schema.org/OpeningHoursSpecification Zawiera „ważne daty”, co jest bardzo przydatne w przypadku niektórych firm.

https://schema.org/docs/search_results.html#q=hours

Powinieneś czuć się dobrze bez klucza podstawowego, chyba że pozwalasz firmom dzielić te same godziny ze stołem do dołączania - co ciekawe, w końcu będziesz miał skończoną liczbę kombinacji; Nie wiem, ile by to było: str

W jednym z moich projektów wykorzystałem kolumny:

[uInt] business_id, [uTinyInt] dzień, [char (11)] timeRange

Jeśli chcesz wspierać OpeningHoursSpecification, musisz dodać validFrom i validThrough.

Zakres czasu ma format: gg: mm-gg: mm

Oto funkcja, która ją analizuje, możesz również zmodyfikować tę funkcję, aby przeanalizować tylko pojedyncze otwarcie / zamknięcie, jeśli zachowasz je jako oddzielne kolumny w bazie danych.

Z mojego doświadczenia radziłbym, abyś zezwalał wiele razy w ciągu dnia, uwzględnij sposób, aby stwierdzić, czy są one wyraźnie zamknięte w tym dniu lub otwarte 24 godziny lub 24/7. Powiedziałem mi, że jeśli brakuje jednego dnia w DB, to tego dnia firma została zamknięta.

/**
 * parseTimeRange
 * parses a time range in the form of
 * '08:55-22:00'
 * @param $timeRange 'hh:mm-hh:mm' '08:55-22:00'
 * @return mixed ['hourStart'=>, 'minuteStart'=>, 'hourEnd'=>, 'minuteEnd'=>]
 */
function parseTimeRange($timeRange)
{
    // no validating just parsing
    preg_match('/(?P<hourStart>\d{1,2}):(?P<minuteStart>\d{2})-(?P<hourEnd>\d{1,2}):(?P<minuteEnd>\d{2})/', $timeRange, $matches);

    return $matches;
}
CTS_AE
źródło
1

Większość wyników działa dobrze w danym scenariuszu, ale nie będzie tak skuteczna, jeśli masz okresy trwające przez wiele dni, np. 8:00 ~ 2:00, wtedy polecam projekt wielookresowy.

   0: [
         id: 1,
         business_id: 1,
         open: true,
         day: 1,
         periods: [
             0: { open: 08:00, close: 23:59 }
         ]
      ],
   1: [
         id: 2,
         business_id: 1,
         open: true,
         day: 2,
         periods: [
             0: { open: 00:00, close: 02:00 }
             1: { open: 08:00, close: 23:59 }
         ]
      ]
Mahmoud Ali Kassem
źródło
0

Warto pomyśleć o faktoringu w święta, dodając dodatkowe pola dla miesiąca roku / dnia miesiąca / tygodnia miesiąca. Tydzień miesiąca ma pewne drobne subtelności „ostatni”, na przykład tydzień 4 lub 5 w zależności od roku.

Einstein
źródło