데이터베이스에 업무 시간 저장


84

저는 현재 업무 시간을 데이터베이스에 저장하는 가장 좋은 방법을 찾고 있습니다.

예를 들면 :

비즈니스 A의 운영 시간은 다음과 같습니다.

  • 월요일 : 오전 9시-오후 5시
  • 화요일 : 오전 9시-오후 5시
  • 수요일 : 9am-5pm
  • 목요일 : 9am-5pm
  • 금요일 : 오전 9시-오후 5시
  • 토요일 : 오전 9시-정오 12시
  • 일요일 : 휴무

현재 다음과 유사한 데이터 모델이 있습니다.

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

여기서 "일"은 코드에서 (ORM을 통해) 요일의 선택으로 제한됩니다. 특정 일에 휴업 여부를 테스트하기 위해 open_time과 close_time이 NULL인지 확인합니다. 중간 테이블 (다 대다 관계)을 통해 비즈니스와 관련됩니다.

이 데이터베이스 체계에 대한 제안이 있습니까? 그것에 대해 뭔가 옳지 않은 것 같습니다.


4
business_hours 테이블과 비즈니스 테이블 사이에 M-to-M 관계가 필요한 이유는 무엇입니까? 정말로 여러 기업이 business_hours에서 동일한 기록을 공유하게하려는 경우, 그 이유는 무엇입니까? 의미 적으로 "회사 C가 D 일에 T1에서 T2로 일한다"는 사실은 엔티티 라기보다는 가치 객체입니다. 제가 상상할 수있는 유일한 좋은 (?) 이유는 스토리지 크기 최적화 (Flyweight 패턴의 RDB 버전, 말하자면) 기업의 수가 엄청날 것으로 예상
된다면

2
점심 시간은 어떻습니까? 공휴일은 어떻습니까?
Mawg는 분석 재개 모니카 말한다

답변:


56

전반적으로 나는 이것에 아무런 문제가 없다고 생각합니다. 외...

  1. 네이티브 프로그래밍 언어가 사용하는 번호 체계를 사용하여 (라이브러리에서) 요일을 정수로 저장합니다. 이렇게하면 데이터베이스 크기가 줄어들고 코드에서 문자열 비교가 제거됩니다.

  2. 이 테이블의 비즈니스 테이블에 외래 키를 넣을 것입니다. 그렇게하면 링크 테이블이 필요하지 않습니다.

그래서 나는 할 것이라고 생각합니다.

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
)

내 비즈니스 로직에서는 모든 "비즈니스" 에 최소 7 개의 "업무 시간" 이 있다는 제약을 적용합니다 . ( 적어도 Jon Skeet의 말이 맞기 때문에 휴일 시간을 원할 수도 있습니다.) 비즈니스가 휴무일 동안 "업무 시간"을 그냥 두어이 제약을 완화하고 싶을 수도 있습니다.


1
2는 어떻게 하시겠습니까? 요일 / 시간이 같은 경우에도 모든 비즈니스에 대한 모든 항목이 있습니까?
Vinko Vrsalovic

7
나는 그렇다고 말할 것입니다. 그렇지 않으면 두 비즈니스가 동일한 시간을 공유하지만 둘 중 하나가 시간을 변경해야하는 경우 어떻게 될지 고려하십시오. 시간이 변경되었다는 사실을 감지하고 공유 여부에 따라 새 레코드를 만들거나 기존 레코드를 편집해야합니다.
Erik Forbes

3
저는이 테이블의 행을 기업간에 공유하지 않을 것입니다. 그런 종류의 공유는 고통으로 이어집니다. 앱의 비즈니스 로직은 모든 ​​비즈니스에 7 개 이상의 "business_hours"참조가 있다는 제약 조건을 적용해야합니다.
Frank Krueger

1
@Vinko : 은 (현재) 동일하지만 두 비즈니스의 영업 시간은 의미 상 다릅니다.
Draemon

1
"일"에 7 비트 비트 맵을 사용할 수도 있습니다. 이렇게하면 동일한 항목을 반복 할 필요가 없습니다. 예를 들어 모든 근무일은 동일한 업무 시간을 가지며 한 항목이면 충분합니다.
ZolaKt 2013

28

이 스키마에서 다루지 않는 한 가지 상황은 하루에 여러 번의 개장 기간입니다. 예를 들어 현지 펍은 12 : 00 ~ 14 : 30 및 17 : 00 ~ 23 : 00에 영업합니다.

마티 네와 저녁 공연을 위해 극장 매표소가 열려있을 수도 있습니다.

이 시점에서 같은 날에 여러 항목을 가질 수 있는지 또는 같은 행에 다른 시간을 표시해야하는지 결정해야합니다.

자정을 넘는 영업 시간은 어떻습니까? 바가 19 : 00-02 : 00에 영업한다고 가정 해 보겠습니다. 개장 및 폐장 시간과 테스트하려는 시간을 비교할 수는 없습니다.


결국 @JordanFeldstein이 제안한 것과 같은 일을했습니다. 나는 변경 (개장 또는 종료), 요일 및 시간을 포함하는 "상태 변경"배열을 저장합니다. 각 비즈니스와 매일에 대해 원하는만큼 "변경"을 가질 수 있습니다. 사업체는 하루에 문을 열었다가 다음 날을 닫을 수 있으며, 하루에 두 번 (또는 x 번) 문을 열고 24 시간 영업하지만 월요일에는 문을 닫습니다. 구현하기가 까다 롭지 만 매우 유연합니다.
ironcito

베스트 답변 접근 방식에 따라 business_hours: break_time및에 두 개의 열을 추가하고 싶습니다 break_duration. 같은 날에 두 번의 휴식을 취하는 것은 정말 드뭅니다.
Frondor

12

데이터를 저장해야하는 대상과 실제 데이터의 모양에 따라 다릅니다.
비즈니스가 특정 시점에 열려 있는지 확인할 수 있어야하는 경우 계획된대로 계획을 쿼리하는 것이 약간 어색 할 수 있습니다. 하지만 더 중요한 것은 다음과 같습니다. 정오 휴무를 준비해야합니까?

일부 옵션은 다음과 같습니다.

  • 당신이 가진 것과 같은 계획이지만 같은 날에 여러 기간을 가질 수있는 옵션이 있습니다. 점심 시간을 제공하지만 사용자에게 프레젠테이션을 위해 주어진 날짜의 영업 시간을 제공하는 쿼리를 실행하는 것은 어색합니다.
  • 비트 맵 스타일 접근법; 9-5의 경우 "000000000111111110000000"입니다. 이 접근 방식의 단점은 특정 세분화, 즉 전체 시간 또는 30 분 또는 실제로는 분을 선택해야한다는 것입니다. 세분성이 높을수록 사람이 데이터를 읽기가 더 어려워집니다. 비트 연산자를 사용하여이 값을 정수 문자열이 아닌 단일 숫자로 저장할 수 있지만 다시 한 번 가독성이 떨어집니다.

11

Google 데이터 마크 업이 귀하의 데이터를 인식하도록하려면 다음 지침을 따라야한다는 것을 배웠습니다.

https://schema.org/openingHours

http://schema.org/OpeningHoursSpecification 일부 비즈니스에 매우 유용한 "유효한 날짜"가 포함되어 있습니다.

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

비즈니스가 조인 테이블과 동일한 시간을 공유하도록 허용하지 않는 한 기본 키 없이도 괜찮습니다. 흥미롭게도 결국에는 제한된 양의 조합을 갖게됩니다. 얼마나 많은지 모르겠습니다 : p

내 프로젝트 중 하나에서 열을 사용했습니다.

[uInt] business_id, [uTinyInt] day, [char (11)] timeRange

OpeningHoursSpecification을 지원하려면 validFrom 및 validThrough를 추가해야합니다.

시간 범위는 hh : mm-hh : mm과 같은 형식입니다.

여기에 그것을 구문 분석하는 함수가 있습니다. DB에 별도의 열로 유지하는 경우 단일 열기 / 닫기 만 구문 분석하도록이 함수를 수정할 수도 있습니다.

내 경험에 비추어 볼 때 하루에 여러 번 허용하고, 그날에 명시 적으로 닫혀 있는지 또는 24 시간 또는 연중 무휴로 열렸는지 알 수있는 방법을 허용하는 것이 좋습니다. DB에 하루가 빠진 날이 있으면 그날 영업이 종료된다고 말했었습니다.

/**
 * 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;
}

1

대부분의 결과는 주어진 시나리오에서 잘 작동하지만, 예를 들어 여러 날에 걸쳐 실행되는 기간이있는 경우에는 효과적이지 않습니다. 8:00 AM ~ 2:00 AM, 그런 다음 다중 기간 디자인을 사용하는 것이 좋습니다.

   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 }
         ]
      ]

0

월 / 일 / 주에 대한 추가 필드를 포함하여 휴일을 고려할 수 있습니다. 한 달의 주에는 몇 가지 사소한 부분이 있습니다. 예를 들어 연도에 따라 4 주 또는 5 주가 될 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.