2010-06-23 5 views
6

Mam tabelę, która podaje godziny otwarcia restauracji. kolumny to id, eateries_id, day_of_week, start_time i end_time. każda knajpka jest reprezentowana w tabeli wiele razy, ponieważ każdy wpis zawiera osobny wpis. zobacz poprzednie pytanie, aby uzyskać więcej informacji: determine if a restaurant is open now (like yelp does) using database, php, jsDrukowanie godziny otwarcia restauracji z tabeli bazy danych w czytelnym formacie człowieka za pomocą php

Zastanawiam się teraz, jak pobrać dane z tej tabeli i wydrukować je w formacie czytelnym dla człowieka. na przykład, zamiast mówić "M 1-3, T 1-3, W 1-3, T 1-3, F 1-8", chciałbym powiedzieć "M-Th 1-3, F 1-8" . podobnie, chcę "M 1-3, 5-8" zamiast "M 1-3, M 5-8". jak mogę to zrobić bez użycia metody brute force wielu instrukcji if?

dzięki.

+1

Czy "m 1-3" jest przechowywane w bazie danych? czy to jest znacznik czasu? –

+0

To interesujący problem ... Postaram się o tym pomyśleć. Przypomina mi to trochę uproszczenia obwodów, które obejmują mapy Karnaugha. Zakładam, że dbasz o podejście wysokiego poziomu i potrafisz obsłużyć odpowiedzi, które nie pasują do twojego stołu. A propos, są dozwolone tylko całe godziny? Kiedy jest najwcześniejsza możliwa godzina i najpóźniejsza możliwa godzina? –

+0

Zacznę od tablicy hash, która mapuje dzień do godzin, takich jak '{'M': set (1,2,3,5,6,7,8), 'T': set (1, 2,3)} 'lub' {'M': 'yyynyyyy'} '(wskazuje, czy dostępna jest każda godzina (tutaj zaczynająca się od 1)). Jest to pierwszy krok do określenia, które 2 dni mają ten sam harmonogram, a także obliczenia i uproszczenia unii godzin otwartych. Dlaczego wszystkie godziny w twoim przykładzie zaczynają się od 1? Czy to późna restauracja? Czy interesuje Cię format 24h? Czy chcesz tam AM i PM? Czy dozwolone są półgodzinne przyrosty? –

Odpowiedz

2

Myślałem, że będę miał na tym bash.

tabeli testowej

CREATE TABLE `opening_hours` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `eateries_id` int(11) DEFAULT NULL, 
    `day_of_week` int(11) DEFAULT NULL, 
    `start_time` time DEFAULT NULL, 
    `end_time` time DEFAULT NULL, 
    PRIMARY KEY (`id`) 
) 

danych testowych

INSERT INTO `test`.`opening_hours` 
(
`eateries_id`, 
`day_of_week`, 
`start_time`, 
`end_time`) 
SELECT 2 AS eateries_id, 1 AS day_of_week, '13:00' AS start_time, '15:00' as end_time union all 
SELECT 2 AS eateries_id, 1 AS day_of_week, '17:00' AS start_time, '20:00' as end_time union all 
SELECT 2 AS eateries_id, 2 AS day_of_week, '13:00' AS start_time, '15:00' as end_time union all 
SELECT 2 AS eateries_id, 2 AS day_of_week, '17:00' AS start_time, '20:00' as end_time union all 
SELECT 2 AS eateries_id, 3 AS day_of_week, '13:00' AS start_time, '15:00' as end_time union all 
SELECT 2 AS eateries_id, 4 AS day_of_week, '13:00' AS start_time, '20:00' as end_time union all 
SELECT 2 AS eateries_id, 5 AS day_of_week, '13:00' AS start_time, '15:00' as end_time union all 
SELECT 2 AS eateries_id, 6 AS day_of_week, '13:00' AS start_time, '20:00' as end_time union all 
SELECT 2 AS eateries_id, 7 AS day_of_week, '13:00' AS start_time, '21:00' as end_time 
                     union all 
SELECT 3 AS eateries_id, 1 AS day_of_week, '13:00' AS start_time, '15:00' as end_time union all 
SELECT 3 AS eateries_id, 2 AS day_of_week, '13:00' AS start_time, '15:00' as end_time union all 
SELECT 3 AS eateries_id, 3 AS day_of_week, '13:00' AS start_time, '15:00' as end_time union all 
SELECT 3 AS eateries_id, 4 AS day_of_week, '13:00' AS start_time, '20:00' as end_time union all 
SELECT 3 AS eateries_id, 5 AS day_of_week, '13:00' AS start_time, '15:00' as end_time union all 
SELECT 3 AS eateries_id, 6 AS day_of_week, '13:00' AS start_time, '20:00' as end_time union all 
SELECT 3 AS eateries_id, 7 AS day_of_week, '13:00' AS start_time, '21:00' as end_time 

Zobacz definicja skonsolidować godziny otwarcia na dzień

CREATE VIEW `test`.`groupedhours` 
AS 
    select `test`.`opening_hours`.`eateries_id` AS `eateries_id`, 
     `test`.`opening_hours`.`day_of_week` AS `day_of_week`, 
     group_concat(concat(date_format(`test`.`opening_hours`.`start_time`,'%l'),' - ',date_format(`test`.`opening_hours`.`end_time`,'%l %p')) order by `test`.`opening_hours`.`start_time` ASC separator ', ') AS `OpeningHours` 
     from `test`.`opening_hours` 
     group by `test`.`opening_hours`.`eateries_id`,`test`.`opening_hours`.`day_of_week` 

Zapytanie znaleźć 'wyspy' z sąsiadujących dni z taka sama godziny otwarcia (na podstawie Itzika Ben Gana)

SET @rownum = NULL; 
SET @rownum2 = NULL; 



SELECT S.eateries_id, 
concat(CASE WHEN 
S.day_of_week <> E.day_of_week 
    THEN 
    CONCAT(CASE S.day_of_week 
      WHEN 1 THEN 'Su' 
      WHEN 2 THEN 'Mo'  
      WHEN 3 THEN 'Tu'  
      WHEN 4 THEN 'We' 
      WHEN 5 THEN 'Th'  
      WHEN 6 THEN 'Fr'  
      WHEN 7 THEN 'Sa' 
      End, ' - ') 
    ELSE ''   
END, 
CASE E.day_of_week 
    WHEN 1 THEN 'Su' 
    WHEN 2 THEN 'Mo'  
    WHEN 3 THEN 'Tu'  
    WHEN 4 THEN 'We' 
    WHEN 5 THEN 'Th'  
    WHEN 6 THEN 'Fr'  
    WHEN 7 THEN 'Sa' 
End, ' ', S.OpeningHours) AS `Range` 
FROM (

SELECT 
    A.day_of_week, 
    @rownum := IFNULL(@rownum, 0) + 1 AS rownum, 
    A.eateries_id, 
    A.OpeningHours 
FROM `test`.`groupedhours` as A 
WHERE NOT EXISTS(SELECT * FROM `test`.`groupedhours` B 
       WHERE A.eateries_id = B.eateries_id 
        AND A.OpeningHours = B.OpeningHours 
        AND B.day_of_week = A.day_of_week -1) 
ORDER BY eateries_id,day_of_week) AS S 

JOIN (
SELECT 
    A.day_of_week, 
    @rownum2 := IFNULL(@rownum2, 0) + 1 AS rownum, 
    A.eateries_id, 
    A.OpeningHours 
FROM `test`.`groupedhours` as A 
WHERE NOT EXISTS(SELECT * FROM `test`.`groupedhours` B 
       WHERE A.eateries_id = B.eateries_id 
        AND A.OpeningHours = B.OpeningHours 
        AND B.day_of_week = A.day_of_week + 1) 
ORDER BY eateries_id,day_of_week) AS E 

ON S.eateries_id = E.eateries_id AND 
    S.OpeningHours = S.OpeningHours AND 
    S.rownum = E.rownum 

Wyniki

eateries_id    Range 
2    Su - Mo 1 - 3 PM, 5 - 8 PM 
2    Tu 1 - 3 PM 
2    We 1 - 8 PM 
2    Th 1 - 3 PM 
2    Fr 1 - 8 PM 
2    Sa 1 - 9 PM 
3    Su - Tu 1 - 3 PM 
3    We 1 - 8 PM 
3    Th 1 - 3 PM 
3    Fr 1 - 8 PM 
3    Sa 1 - 9 PM 
+1

To jest interesujące. Moim zdaniem SQL powinno szybko uzyskać dane, ponieważ jest to najlepsze rozwiązanie. Masowanie najlepiej jest zrobić (jak sądzę) przy użyciu języka wyższego poziomu. Twój SQL jest jednak imponujący. –

2

Chcesz unii kilka przedziałów dla każdego dnia. Trzymaj się formatu 24-godzinnego (najpierw przekonwertuj go na sekundy), aż będziesz musiał przekonwertować go do formatu bardziej przyjaznego człowiekowi.

http://pyinterval.googlecode.com/svn/trunk/html/index.html

Problem jest to, że kiedy pozwalasz sekund ... restauracja, która zamyka 1 sekundy wcześniej zostaną pominięte :(Może trzeba pozwolić co 15 lub 5-minutowe. Okrągły danych w DB jeżeli Tak więc, podejście polega na: użyciu struktury danych przedziałowych, związaniu wszystkich przedziałów dla danego dnia razem Teraz odwróć słownik, zamiast mapowania dni na interwały, odstępy czasu na mapie do dni Teraz znajdź sposób na reprezentowanie tych grup dni inteligentnie, na przykład set(1,2,3) może być wyświetlany jako "MW", więc sugerowałbym: dla każdego zestawu mocy zestawu {1,2,3,4,5,6,7} (lub {1,2,3,4,5}) znajdź najlepszą ludzką reprezentację (ręcznie). Teraz zakoduj tę logikę - zapisz go na di ctionary, który mapuje posortowany ciąg znaków (jest to ważny), taki jak "1235", na reprezentację ludzką, taką jak "M-W, F". Wyświetlanie 1-3, 5-8 jest łatwe, gdy pracujesz z obiektem interwału, jak opisano w powyższym linku. Powodzenia! Daj mi znać, jakie problemy napotkasz.

EDIT:

To nie jest najlepszy przykład, że mają (nie pokazują jedność nakładających odstępach czasu), ale trzeba dbać o „|” Operator

unioned: 

>>> interval[1, 4] | interval[2, 5] 
interval([1.0, 5.0]) 

>>> interval[1, 2] | interval[4, 5] 
interval([1.0, 2.0], [4.0, 5.0]) 

Można tylko wdrożenie tej klasy siebie, ale to może być podatne na błędy.

+0

Tutaj zakładałem, że Mon = 1, Tue = 2, ... Sun = 7, ponieważ jest to konwencja w niektórych krajach - tydzień rozpoczyna się w poniedziałek, a kończy w niedzielę. http://www.cjvlang.com/Dow/SunMon.html –

+0

Wydaje mi się, że rozumiem, co mówisz .. chociaż nie byłoby ponad setki kombinacji dni, które musiałbym napisać na sztywno? – vee

+0

Niezupełnie, 2^5 = 32; 2^7 = 128 :) Jednak mogą one zostać wygenerowane. –