문제

우리는 다양한 비즈니스의 "영업 시간"을 저장하는 앱을 구축하고 있습니다.항목이 열려 있는지 쉽게 확인할 수 있도록 이 데이터를 표현하는 가장 쉬운 방법은 무엇입니까?

일부 옵션:

  • "개방/폐쇄"로 표시할 수 있는 블록을 분할합니다(15분마다).확인에는 "열림" 비트가 원하는 시간(기차 시간표와 약간 유사)으로 설정되어 있는지 확인하는 것이 포함됩니다.
  • 시간 범위(오전 11시~오후 2시, 오후 5~7시 등) 목록을 저장하고 현재 시간이 지정된 범위에 속하는지 확인합니다(위 문자열을 구문 분석할 때 우리 두뇌가 수행하는 작업입니다).

시간표 정보와 조언을 저장하고 쿼리한 경험이 있는 사람이 있나요?

("매월 첫 번째 화요일 휴무"와 같은 이상한 경우가 많지만 이에 대해서는 다른 날에 남겨 두겠습니다).

도움이 되었습니까?

해결책

각각의 연속 시간 블록을 시작 시간과 지속 시간으로 저장하십시오. 이렇게하면 시간이 다가오는 시간을 쉽게 확인할 수 있습니다.

운영 시간이 날짜 경계를 넘지 않을 것이라고 확신한다면 (즉, 공개 밤 판매 또는 72 시간 마라톤 이벤트 등) 시작/종료 시간으로 충분합니다.

다른 팁

가장 유연한 솔루션은 Bitset 접근법을 사용하는 것입니다. 일주일에 168 시간이므로 672 분 15 분이 있습니다. 그것은 단지 84 바이트 상당의 공간이며, 이는 견딜 수 있어야합니다.

나는 다음과 같은 테이블을 사용할 것입니다.

BusinessID | weekDay | OpenTime | CloseTime 
---------------------------------------------
     1          1        9           13
     1          2        5           18
     1          3        5           18
     1          4        5           18
     1          5        5           18
     1          6        5           18
     1          7        5           18

여기에는 정기적 인 시간이 5 ~ 6 시간이지만 일요일에는 더 짧은 사업이 있습니다.

Open이 될 경우 쿼리 (psuedo-sql)

SELECT @isOpen = CAST
   (SELECT 1 FROM tblHours 
       WHERE BusinessId = @id AND weekDay = @Day 
       AND CONVERT(Currentime to 24 hour) IS BETWEEN(OpenTime,CloseTime)) AS BIT;

Edge Case를 저장 해야하는 경우 하루에 한 번 365 개의 항목 만 가지고 있습니다. 실제로는 그랜드 체계에서 그다지 많지 않습니다.

비즈니스 타임 존을 별도의 테이블 (정상화!)에 보관하고 이러한 비교를하기 전에 시간과 IT 간의 변화를 수행하는 것을 잊지 마십시오.

저는 개인적으로 시작 + 종료 시간을 선택하는 것이 모든 것을 더 유연하게 만들어 줄 것이라고 생각합니다.좋은 질문은 다음과 같습니다:특정 시점에서 블록 크기가 변경될 가능성은 얼마나 됩니까?그런 다음 귀하의 상황에 가장 적합한 솔루션을 선택하십시오(변경할 가능성이 있는 경우에는 확실히 기간을 정할 것입니다).

이를 기간으로 저장하고 애플리케이션에서 세그먼트를 사용할 수 있습니다.이렇게 하면 데이터 저장소를 변경할 수 있는 유연성을 유지하면서 블록을 사용하여 쉽게 입력할 수 있습니다.

Johnathan Holland에 추가합니다 말했다, 나는 같은 날에 여러 개의 출품작을 허용 할 것입니다.

또한 소수점 또는 몇 분 동안 다른 열을 허용합니다.

왜요? 많은 레스토랑과 일부 비즈니스 및 전 세계의 많은 비즈니스에는 점심 및 오후 휴식이 있습니다. 또한, 많은 식당 (2 명은 홀수 15 인상 시간에 내 집 근처에 있다는 것을 알고있는 2 명이 일요일 오후 9시 40 분에 닫히고 오전 1시 40 분에 문을 닫습니다.

예를 들어 추수 감사절 초에 매장이 문을 닫는 것과 같은 휴가 시간 문제도 있으므로 캘린더 기반 재정의가 필요합니다.

아마도 다음과 같은 날짜/시간 개방, 날짜 시간 마감일 것입니다.

businessID  | datetime              | type
==========================================
        1     10/1/2008 10:30:00 AM    1
        1     10/1/2008 02:45:00 PM    0
        1     10/1/2008 05:15:00 PM    1
        1     10/2/2008 02:00:00 AM    0
        1     10/2/2008 10:30:00 AM    1

등 (유형 : 1 개방 및 0 폐쇄)

그리고 앞으로 1 ~ 2 년의 모든 날은 1-2 년 전에 미리 계산했습니다. int, date/time/bit : 데이터 소비가 최소화되어야합니다.

이를 통해 특별한 날의 홀수 시간에 대한 특정 날짜를 수정할 수 있습니다.

또한 자정과 12/24 시간 전환을 교차시켜야합니다.

또한 시간대 불가지론입니다. 시작 시간과 지속 시간을 저장하는 경우 종료 시간을 계산할 때 컴퓨터가 TZ 조정 시간을 제공합니까? 너가 원하는게 그거야? 더 많은 코드.

Open-Closed 상태에 대한 쿼리에 관한 한 : 해당 날짜 시간을 쿼리하십시오.

select top 1 type from thehours where datetimefield<=somedatetime and businessID = somebusinessid order by datetime desc

그런 다음 "타입"을보십시오. 하나가 열리면 0이면 닫힙니다.

추신 : 저는 10 년 동안 소매에있었습니다. 그래서 저는 소규모 비즈니스 미친 시간 문제에 익숙합니다.

좋아, 가치가 있는 일이라면 이 문제를 다루겠습니다.

꽤 많은 일을 처리해야 해요.

  • 빠르고 효율적인 쿼리
  • 시간 증분(오후 9시 1분, 12시 14분 등)
  • 국제(?) - 이것이 시간대에도 문제가 되는지 확실하지 않습니다. 적어도 내 경우에는 여기에 더 정통한 사람이 자유롭게 의견을 교환할 수 있습니다.
  • 오픈 - 다음날까지 마감(정오 오픈, 오전 2시 마감)
  • 여러 시간대/일
  • 특정 날짜(공휴일 등)를 재정의하는 기능
  • 재정의가 반복되는 기능
  • 특정 시점을 쿼리하고 영업을 시작하는 기능(현재, 미래 시간, 과거 시간)
  • 곧 폐업하는 업체 결과를 쉽게 제외하는 기능(30분 후에 폐업하는 업체를 필터링합니다. 사용자를 '음식/음료 산업에서 폐업 5분 전에 나타나는 사람'으로 만들고 싶지는 않습니다.)

나는 제시된 많은 접근법을 좋아하며 그 중 몇 가지를 차용하고 있습니다.내 웹사이트, 프로젝트 등 내가 고려해야 할 사항이 무엇이든 수백만 개의 비즈니스가 있을 수 있으며 여기에 있는 몇 가지 접근 방식은 개인적으로 나에게 적합하지 않은 것 같습니다.

알고리즘과 구조에 대해 제가 제안하는 내용은 다음과 같습니다.

우리는 언제 어디서나 전 세계에 걸쳐 몇 가지 구체적인 가정을 해야 합니다.일주일은 7일입니다.하루는 1440분입니다.가능한 개방/폐쇄 시간(분)의 순열 수에는 제한이 있습니다.

구체적이지는 않지만 괜찮은 가정:공개/마감 시간의 많은 순열이 기업 전체에서 공유되어 실제로 저장된 총 순열을 줄입니다.내 인생에서 이 접근 방식에 대한 실제 가능한 조합을 쉽게 계산할 수 있었던 때가 있었지만 누군가 도움을 줄 수 있거나 그것이 유용할 것이라고 생각한다면 그것은 좋을 것입니다.

나는 3개의 테이블을 제안한다:읽기를 중단하기 전에 실제로 이러한 테이블 중 2개는 캐시가 충분히 작을 것이라는 점을 고려하십시오.이 접근 방식은 UI를 데이터 모델로 해석하고 필요한 경우 다시 해석하는 데 필요한 코드의 복잡성으로 인해 모든 사람에게 적합한 것은 아닙니다.귀하의 마일리지와 요구 사항은 다를 수 있습니다.이는 그것이 의미하는 바가 무엇이든 합리적인 '기업' 수준 솔루션을 시도하는 것입니다.

HoursOfOperations 테이블

id | 열기 (1 분) | 닫기 (1 분)


1 | 360 | 1020 (예 :오전 9시 - 오후 5시)

2 | 365 | 1021 (예 :극단적인 경우 오전 9:05 - 오후 5:01(이상한 사람)

등.

HoursOfOperations는 요일에 신경 쓰지 않고 단지 열고 닫고 고유성을 유지합니다.열기/닫기 조합당 하나의 항목만 있을 수 있습니다.이제 환경에 따라 이 전체 테이블을 캐시할 수도 있고 현재 시간 등에 대해 캐시할 수도 있습니다.어쨌든 모든 작업에 대해 이 테이블을 쿼리할 필요는 없습니다.귀하의 스토리지 솔루션에 따라 이 테이블의 모든 열이 성능을 위해 인덱싱된 것으로 생각됩니다.시간이 지남에 따라 이 테이블은 INSERT의 가능성이 기하급수적으로 역전될 가능성이 높습니다.하지만 실제로는 이 테이블을 처리하는 것이 대부분 RAM(In Process Operation)이어야 합니다.

Business2HoursMap

메모:내 예에서는 "Day"를 비트 플래그 필드/열로 저장합니다.이는 주로 내 필요와 C#의 LINQ/Flags Enums 발전 때문입니다.이것을 7비트 필드로 확장하는 것을 막을 수 있는 것은 없습니다.두 접근 방식 모두 저장소 논리와 쿼리 접근 방식 모두 상대적으로 유사해야 합니다.

또 다른 참고사항:나는 "모든 테이블에 PK ID 열이 필요합니다"에 대한 의미론적 주장을 시작하지 않습니다. 이에 대한 다른 포럼을 찾으십시오.

businessid | Hoursid | 날 (또는 분할을 선호하는 경우 :BIT 월요일, BIT 화요일, ...)


1 | 1 | 1111111 (이 사업은 매주 9-5 명입니다)

2 | 2 | 1111110 (이 사업은 9:05-5:01 M -SAT입니다 (월요일 = 1 일)

이것이 쿼리하기 쉬운 이유는 우리가 추구하는 MOTD(오늘의 분)를 항상 아주 쉽게 결정할 수 있기 때문입니다.내일 오후 5시에 영업하는 곳이 무엇인지 알고 싶으면 모든 HoursOfOperations IDS WHERE Close >= 1020을 가져옵니다.시간 범위를 찾고 있지 않는 한 Open은 중요하지 않습니다.다음 30분 안에 업체가 문을 닫는 모습을 표시하지 않으려면 그에 맞게 들어오는 시간을 조정하세요(오후 5시(1020)가 아닌 오후 5시 30분(1050)을 검색하세요.두 번째 쿼리는 당연히 'HoursID IN(1, 2, 3, 4, 5) 등의 모든 비즈니스를 나에게 제공합니다.이 접근 방식에는 제한이 있으므로 이는 위험 신호를 발생시킬 수 있습니다.그러나 누군가 위의 실제 순열 질문에 답할 수 있다면 우리는 위험 신호를 내릴 수 있습니다.개방형이든 폐쇄형이든 한 번에 방정식의 한쪽 측면에 가능한 순열만 필요하다고 생각해 보세요.

첫 번째 테이블이 캐시되어 있다는 점을 고려하면 이는 빠른 작업입니다.두 번째 작업은 잠재적으로 큰 행 테이블을 쿼리하는 것이지만 우리는 매우 작은(SMALLINT) 인덱스 열을 검색하고 있습니다.

이제 코드 측면의 복잡성을 확인할 수 있습니다.나는 내 특정 프로젝트에서 주로 바를 대상으로 하고 있으므로 "오전 11시 - 오전 2시(다음날)"와 같은 영업 시간을 가진 상당한 수의 비즈니스가 있을 것이라고 가정하는 것이 매우 안전할 것입니다.이는 실제로 HoursOfOperations 테이블과 Business2HoursMap 테이블 모두에 2개의 항목이 됩니다.예:오전 11시부터 오전 2시까지 영업하는 바에는 HoursOfOperations 테이블 660 - 1440(오전 11시 - 자정) 및 0 - 120(자정 - 오전 2시)에 대한 2개의 참조가 있습니다.이러한 참조는 단순한 경우 2개의 항목으로 Business2HoursMap 테이블의 실제 날짜에 반영됩니다. 1개 항목 = 하루 종일 시간 참조 #1, 또 다른 하루 참조 #2.말이 되기를 바랍니다. 긴 하루였습니다.

특별한 날/공휴일/무엇이든 재정의합니다.재정의는 본질적으로 요일 기반이 아닌 날짜 기반입니다.나는 이것이 속담의 둥근 말뚝을 사각형 구멍에 밀어 넣으려는 접근 방식 중 일부라고 생각합니다.테이블이 하나 더 필요해요.

Hoursid | businessid | 일 | 달 | 년도

1 | 2 | 1 | 1 | 없는

"매 두 번째 화요일에 이 회사는 4시간 동안 낚시를 갑니다"와 같은 것이 필요한 경우에는 확실히 더 복잡해질 수 있습니다.그러나 이를 통해 매우 쉽게 수행할 수 있는 작업은 1 - 재정의, 2 - 합리적인 반복 재정의를 허용하는 것입니다.예를 들어연도가 NULL이면 매년 설날 이 이상한 바는 위의 데이터 예에 따라 오전 9시부터 오후 5시까지 열립니다.즉.- 연도를 설정한 경우 2013년으로만 설정됩니다.월이 null인 경우 해당 월의 모든 1일이 됩니다.다시 말하지만, 이는 NULL 열만으로 모든 일정 시나리오를 처리할 수는 없지만 이론적으로는 필요한 경우 절대 날짜의 긴 순서를 사용하여 거의 모든 것을 처리할 수 있습니다.

이번에도 이 테이블을 롤링 데이 단위로 캐시하겠습니다.하루 동안의 스냅샷에서 이 테이블의 행이 적어도 내 필요에 비해 매우 크다는 것을 현실적으로 볼 수 없습니다.이 테이블이 재정의되었으므로 먼저 이 테이블을 확인하고 스토리지 측의 훨씬 더 큰 Business2HoursMap 테이블에 대한 쿼리를 저장합니다.

흥미로운 문제입니다.이 문제를 깊이 생각해야 했던 것은 이번이 처음이라는 사실에 정말 놀랐습니다.언제나 그렇듯이 내 접근 방식의 다양한 통찰력, 접근 방식 또는 결함에 매우 관심이 많습니다.

세그먼트 블록이 더 좋습니다. 사용자에게 쉽게 설정할 수있는 방법을 제공하십시오. 클릭하고 드래그가 좋습니다.

자정 경계를 넘을 때 다른 시스템 (예 : 범위)은 정말로 성가 시게됩니다.

C ++ 비트 필드에서 저장하는 방법에 관해서는 아마도 가장 좋을 것입니다. 대부분의 다른 언어에서는 배열이 더 좋을 수 있습니다 (많은 낭비 공간이지만 더 빠르게 실행되고 이해하기가 더 쉽습니다).

나는 당신이 기본 구성과 오버레이 오버레이 또는 개방 시간의 완전한 정적 저장을 가지고 있는지 여부를 알리기 때문에 지금 당장 그 엣지 케이스에 대해 조금 생각할 것입니다.

많은 예외가 있으며, 정기적으로 (눈의 날, 부활절, 성 금요일과 같은 불규칙한 휴일)와 같은 경우, 이것이 현실을 신뢰할 수있는 현실 표현으로 예상되면 (좋은 추측과 반대로) 필요합니다. 아키텍처에서 곧 해결하기 위해.

다음과 같은 것은 어떻습니까?

매장 영업시간표

Business_id (int)
Start_Time (time)
End_Time (time)
Condition varchar/string
Open bit

'조건'은 람다 식('where' 절에 대한 텍스트)입니다.쿼리를 동적으로 작성합니다.따라서 특정 비즈니스에 대해 모든 영업/폐업 시간을 선택합니다.

Let Query1 = select count(open) from store_hours where @t between start_time and end_time and open  = true and business_id = @id and (.. dynamically built expression)

Let Query2 = select count(closed) from store_hours where @t between start_time and end_time and open = false and business_id = @id and (.. dynamically built expression)

따라서 다음과 같이 원하는 끝을 끝내십시오.

select cast(Query1 as bit) & ~cast(Query2 as bit)

마지막 쿼리의 결과가 1이면 상점은 시간 t에 열려 있고, 그렇지 않으면 닫혀 있습니다.

이제 where 절(람다 표현식)을 생성할 수 있는 친숙한 인터페이스만 있으면 됩니다.

내가 생각할 수 있는 유일한 또 다른 특수 사례는 상점이 특정 날짜에 오전 7시부터 오전 2시까지 열려 있지만 다음 날짜에는 오후 11시에 문을 닫는 경우에 발생하는 것입니다.귀하의 시스템은 이틀 간의 시간을 스마트하게 분할하여 이를 처리할 수도 있어야 합니다.

여기서 메모리를 절약 할 필요는 없지만 깨끗하고 이해할 수있는 코드가 필요할 수 있습니다. "Bit Twiddling"은 IMHO가 아닙니다.

여기에는 세트 컨테이너가 필요합니다. 여기에는 고유 한 품목이 다수의 고유 한 항목을 보유하고 있으며 항목이 멤버인지 아닌지 신속하고 쉽게 결정할 수 있습니다. 설정은 Reuires Care를 관리하지만 일상적으로 사용하면 단순히 이해되는 코드의 한 줄은 열려 있는지 또는 닫혀 있는지 결정합니다.

개념 : 자정 일요일부터 시작하여 15 분마다 인덱스 번호를 지정합니다.

초기화 : 열면 15 분마다 인덱스 번호를 세트에 삽입하십시오. (당신이 문을 닫는 것보다 더 적은 시간을 열고 있다고 가정합니다.)

사용 : 흥미로운 시간, 몇 분 만에, 전일 일요일 자정에 15로 나눕니다.이 숫자가 세트에 있으면 열려 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top