Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Złożony warunek dla dwóch DATETIME
Forum PHP.pl > Forum > Bazy danych > MySQL
ktuvok
W tabeli "Zdarzenia" mam dwa pola typu DATETIME: DataB i DataC.

Jest następująca reguła:
- jeśli DataB jest przed godziną 13:00, to DataC musi być datą z tego samego
dnia,
- jeśli DataB jest po 13:00, to:
- jeśli DataB jest piątkowa, to DataC musi być datą z najbliższego
poniedziałku do godziny 12:00 (szerzej - najbliższego dnia roboczego, ale
nie będę się czepiał...),
- w przeciwnym wypadku DataC musi być datą z dnia następnego w stosunku
do DataB, do godziny 12:00.

Jak wybrać wszystkie zdarzenia zapisane w bazie, nie spełniające tej reguły?

MySQL 4.0.18 (brak podselectów).

Pozdrawiam,
Krzysiek
popbart
  1. SELECT pole1, IF(time(DataB)<'13:00:00' AND date(DataB)=date(DataC),'true',
  2. IF(time(DataB)>'13:00:00' AND dayname(DataB)='Friday' AND dayname(DataC)='Monday' AND time(DataC)<'12:00:00','true',
  3. IF(time(DataB)>'13:00:00' AND dayname(DataB)!='Friday' AND date(DataC)=date(DataB) + interval 1 day AND time(DataC)<12:00,'true','false'))
  4. AS warunek FROM tabela WHERE warunek='false'


Pozdrawiam,
Bartek
ktuvok
Dzięki za zainteresowanie, to dosyć ciekawe rozwiązanie...

Ale w MySQL nie ma funkcji TIME ani DATE. Można je zamienić odpowiednio HOUR i DATE_FORMAT, co zresztą uczyniłem. Nie da się również w klauzuli WHERE użyć aliasu "warunek"; jedyne co mi przyszło do głowy to zamiana WHERE na HAVING.

Wyszło mi coś takiego:
  1. SELECT IDRekordu,
  2. IF(
  3. HOUR(DataB)<'13' AND DATE_FORMAT(DataB,'%Y-%m-%d')=DATE_FORMAT(DataC,'%Y-%m-%d'),'true',
  4. IF(
  5. HOUR(DataB)>'13' AND DAYNAME(DataB)='Friday' AND DAYNAME(DataC)='Monday' AND HOUR(DataC)<'12','true',
  6. IF(
  7. HOUR(DataB)>'13' AND DAYNAME(DataB)!='Friday' AND DATE_FORMAT(DataC,'%Y-%m-%d')=DATE_FORMAT(DataB,'%Y-%m-%d') + INTERVAL 1 DAY AND HOUR(DataC)<'12','true','false'
  8. )
  9. )
  10. )
  11. AS warunek FROM Zdarzenia HAVING warunek='false'


Tyle że to zapytanie jest skrajnie nieoptymalne - skanuje całą tabelę i nie wiedzieć czemu nie korzysta z indeksów, chociaż są wszędzie, gdzie być powinny. Zapewne to wina użycia HAVING zamiast WHERE.

Poza tym jeśli chcę dodać kolejny warunek, np. wybór zdarzeń od ... do ..., to muszę umieścić kolejnego IF'a zamiast prostego WHERE DataB BETWEEN ... AND ... , prawda?

Reasumując - nie da się jakoś prościej?

Pozdrawiam,
Krzysiek
popbart
Co do time i date to zapomniałem dodać że są one dostępne dopiero od wersji 4.1.1.
Z tym having masz rację.
Warunek where możesz spokojnie wstawić przed klauzulą having i tam dawać jakieś inne warunki typu between.
Cytat
Tyle że to zapytanie jest skrajnie nieoptymalne - skanuje całą tabelę i nie wiedzieć czemu nie korzysta z indeksów, chociaż są wszędzie, gdzie być powinny. Zapewne to wina użycia HAVING zamiast WHERE.

A masz ustawione indeksy na pola DataB i DataC ?
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.