![]() |
![]() ![]() |
![]() |
![]()
Post
#1
|
|
![]() Grupa: Moderatorzy Postów: 6 072 Pomógł: 861 Dołączył: 10.12.2003 Skąd: Dąbrowa Górnicza ![]() |
Mam tabelę z danymi:
201501;100 201502;80 ... czyli rok i miesiąc (jako liczba) oraz jakaś wartość liczbowa. Kolumn w sumie jest nieco więcej i dla każdego miesiąca mam tak naprawdę ~1800 rekordów ale nie ma to większego znaczenia dla problemu. Potrzebuję teraz przedstawić dane w ujęciu tygodniowym tj. jaka wartość przypada na każdy tydzień roku. Problemem jest tutaj fakt, ze tygodnie mogą zachodzić na 2 miesiące. Czy jest jakiś sprytny sposób żeby to ogarnąć po stronie bazy? Na chwile obecną tworzę tabelę tymczasową dla pojedynczych dni na zasadzie selectów połączonych unionami (mam więc 365 takich selectów). Dla każdego dnia wstawiam: wartość dla miesiąca / liczba dni w miesiącu a następnie korzystam z tej tabeli z użyciem funkcji week(). Może jest jakieś szybsze rozwiązanie? |
|
|
![]()
Post
#2
|
|
![]() Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%) ![]() ![]() |
W jaki sposób rozróżniasz jakie dane należą do jakiego tygodnia skoro w bazie danych masz informację jedynie co do roku i miesiąca?
|
|
|
![]()
Post
#3
|
|
![]() Grupa: Moderatorzy Postów: 6 072 Pomógł: 861 Dołączył: 10.12.2003 Skąd: Dąbrowa Górnicza ![]() |
Napisałem przecież: jeśli wartość dla stycznia to 310 to na jeden dzień stycznia przypada 10, do tabeli tymczasowej wstawiam więc 10 dla 2015-01-01, 2015-01-02, ..., 2015-01-31. Mając wartość rozbitą na dni mogę skorzystać z funkcji week(). Rozwiązanie niestety nie jest wybitnie wydajne z racji tabeli tymczasowej tworzonej przy każdym wyświetleniu raportu. Jeśli nikt nie zasugeruje niczego innego to chyba zrobię osobną tabelę z odpowiednimi indeksami zawierającą już rozbite dane. Tabela byłaby aktualizowana triggerem w momencie zasilania tabeli zagregowanej. Wydajność powinna być lepsza ale kosztem zdublowanie danych.
|
|
|
![]()
Post
#4
|
|
Grupa: Zarejestrowani Postów: 6 806 Pomógł: 1828 Dołączył: 11.03.2014 Ostrzeżenie: (0%) ![]() ![]() |
Proponuję tabelę kalendarz:
miesiac, data 01, 2015-01-01 01, 2015-01-02 ... 01, 2015-01-31 02, 2015-02-01 02, 2015-02-02 ... 02, 2015-02-28 itd. tabela ilosc: data, ilosc 201501, 100 201502, 150 itd.
Zapytanie jest poprawne jeśli kalendarz oraz dane są na jeden rok. Inaczej trzeba tabelę kalendarz i warunek w zapytaniu rozbudować. -------------------- |
|
|
![]()
Post
#5
|
|
![]() Grupa: Moderatorzy Postów: 6 072 Pomógł: 861 Dołączył: 10.12.2003 Skąd: Dąbrowa Górnicza ![]() |
Właśnie o tego typu podpowiedź mi chodziło. Jutro będę kombinował z podejściem kalendarzowym, dzięki!
|
|
|
![]()
Post
#6
|
|
Grupa: Zarejestrowani Postów: 60 Pomógł: 10 Dołączył: 17.11.2011 Ostrzeżenie: (0%) ![]() ![]() |
Można kombinować jeszcze z jednym zapytaniem, czyli podzielić stringa data i stworzyć datę na której da się użyć week.
Czyli coś takiego:
Można przemyśleć na optymalizacją tego zapytania,a jak się będzie zachowywało przy większej liczbie rekordów to trzeba byłoby przetestować. Ten post edytował DarkAbso 23.06.2015, 21:25:22 |
|
|
![]()
Post
#7
|
|
![]() Grupa: Moderatorzy Postów: 6 072 Pomógł: 861 Dołączył: 10.12.2003 Skąd: Dąbrowa Górnicza ![]() |
Chyba sie nie zrozumieliśmy. Średnik w przykładowych danych oddziela 2 kolumny. Rok i miesiąc mam zapisane w 1 kolumnie jako liczbę, a ta druga wartość to po prostu jakaś liczba przypisana do danego okresu. Idąc Twoim tokiem rozumowania chyba jednak nie będę w stanie nic sensownego osiągnąć. Tak czy inaczej dzięki za odzew.
|
|
|
![]()
Post
#8
|
|
Grupa: Zarejestrowani Postów: 60 Pomógł: 10 Dołączył: 17.11.2011 Ostrzeżenie: (0%) ![]() ![]() |
Rzeczywiście nie dogadaliśmy się, a moje rozwiązanie traci sens. W takim razie rozwiązanie @trueblue będzie najrozsądniejsze. Jak by to była inna baza to ewentualnie można było by sobie stworzyć funkcję zwracającą tabelę kalendarz i do niej się JOIN'ować, ale niestety w Mysql to nie przejdzie.
Ten post edytował DarkAbso 23.06.2015, 22:09:55 |
|
|
![]()
Post
#9
|
|
Grupa: Zarejestrowani Postów: 6 806 Pomógł: 1828 Dołączył: 11.03.2014 Ostrzeżenie: (0%) ![]() ![]() |
Jeszcze można uprościć.
kalendarz wystarczy, że będzie zawierał tylko daty. Warunek wtedy:
-------------------- |
|
|
![]()
Post
#10
|
|
![]() Grupa: Moderatorzy Postów: 6 072 Pomógł: 861 Dołączył: 10.12.2003 Skąd: Dąbrowa Górnicza ![]() |
Rozwiązanie ~trueblue spisuje się wybornie. Utworzyłem tabelę calendar_date_period z kolumnami:
date - data, np. 2015-01-01, klucz główny period - okres czyli rokmiesiąc, np. 201501, indeks. Joinuję do tej tabeli po kolumnie period, otrzymuję wszystkie dni danego okresu, a wartości traktuję poprzez:
Całość działa bardzo sprawnie. Trzeba tylko pamiętać by w tabeli calendar_date_period mieć odpowiedni zakres danych - ja wygenerowałem sobie do 2030-12-31 ![]() |
|
|
![]()
Post
#11
|
|
Grupa: Zarejestrowani Postów: 60 Pomógł: 10 Dołączył: 17.11.2011 Ostrzeżenie: (0%) ![]() ![]() |
Hyhy teraz pozostało Tobie tylko zapamiętać, aby wygenerować kolejne dane za 15 lat.
![]() |
|
|
![]() ![]() |
![]() |
Wersja Lo-Fi | Aktualny czas: 15.08.2025 - 04:08 |