Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Zliczanie w przelocie, czy zapis do bazy
jsmp
post 21.02.2014, 00:23:23
Post #1





Grupa: Zarejestrowani
Postów: 20
Pomógł: 1
Dołączył: 25.01.2009

Ostrzeżenie: (0%)
-----


Mam dylemat, jak realizować pewne funkcje statystyczne. Przykładowo codziennie scrapuje sobie kurs waluty. Zapisuje sobie w bazie wg formatu: data | kurs_dnia.

Pytanie, czy np. aby opracować sobie np. średnią przyrostu/spadku z np. 100 pozycji, musiałoby to oznaczać robienie w locie obliczania z surowych danych tego przy każdym wywołaniu witryny. Czy zatem nie lepiej sobie przy zaciąganiu danych od razu powyliczać niektóre dane?

Mam też podobny dylemat jeśli chodzi np. o obliczanie przyrostów dla poszczególnych dni, wtedy ilość operacji była by jeszcze większa - bo dla każdej daty trzeba by było sprawdzić jaki to dzień tygodnia, wyciągnąć wartości osobno dla pon, wt, śr... itd, i dopiero tu zrobić średnią wg dni tygodnia.


--------------------
WebSEM.pl - Jak promować stronę internetową? - marketing internetowy i nie tylko...
Go to the top of the page
+Quote Post
ghost1511
post 21.02.2014, 09:49:47
Post #2





Grupa: Zarejestrowani
Postów: 186
Pomógł: 18
Dołączył: 2.09.2010

Ostrzeżenie: (0%)
-----


Pytasz o to czy od razu pobierać średnią z bazy czy liczyć ją dopiero w php?
Go to the top of the page
+Quote Post
jsmp
post 21.02.2014, 10:39:16
Post #3





Grupa: Zarejestrowani
Postów: 20
Pomógł: 1
Dołączył: 25.01.2009

Ostrzeżenie: (0%)
-----


Nie. To rozumiem, że jest wygodniejsze w zapytaniu. Chodzi mi o sytuację gdy:

2014-02-19 | 321
2014-02-20 | 322
2004-02-21 | 330

I, chce pokazać użytkownikom wzrost pomiędzy wartościami. Mogę to obliczać żywcem biorąc z bazy i lecąc za każdym wywołaniem php wartość(dziś) - wartość (dziś-1), druga opcja to zapisanie tego w taki sposób, żeby przyrost był od razu zapisywany:
2014-02-19 | 321 | -
2014-02-20 | 322 | 1
2004-02-21 | 330 | 8

Taki sam dylemat mam odnośnie kwestii statystycznej, np. chcąc zrobić porównanie wzrostów wg dni tygodnia. Czy lepiej w przelocie sprawdzać jaki dzień tygodnia wynika z daty, czy w nowej kolumnie DB zapisać dzień tygodnia jako 1-7. Ułatwia to selekcję danych potem, stosując WHERE, bez tego niestety za każdym razem musiałbym to ustalać php'em.

Ten post edytował jsmp 21.02.2014, 10:39:58


--------------------
WebSEM.pl - Jak promować stronę internetową? - marketing internetowy i nie tylko...
Go to the top of the page
+Quote Post
phpion
post 21.02.2014, 11:19:55
Post #4





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




1. Jeżeli dane masz zapisywane dzień po dniu bez luk w dniach to możesz pozostać przy strukturze data, wartość. Wystarczy wówczas, że dołączysz (LEFT JOIN - LEFT by uwzględnić też pierwszy wynik) jeszcze raz tą samą tabelę (pamiętając o aliasie) na warunku (ON) poprzedni.data = biezacy.data - 1 dzien. No i zwykłym odejmowaniem obliczysz różnicę (pamiętając o COALESCE(poprzedni.wartosc, 0) żeby uniknąć NULLi). Jeśli natomiast mogą być luki w datach to nie możesz zrobić opisanego JOINa, bo zapewne chciałbyś uzyskać dane dla dnia poprzedniego zapisanego w bazie (czyli jeśli nie ma danych za wczoraj, to weź z przedwczoraj). Chyba, że miałyby Cię interesować tylko dni poprzednie - wówczas możesz zostać przy JOINie.

2. Dzień tygodnia możesz wyczaić w samym SQL: http://dev.mysql.com/doc/refman/5.5/en/dat...ction_dayofweek
Go to the top of the page
+Quote Post
ghost1511
post 21.02.2014, 11:24:47
Post #5





Grupa: Zarejestrowani
Postów: 186
Pomógł: 18
Dołączył: 2.09.2010

Ostrzeżenie: (0%)
-----


Wydaje mi się że jeżeli chcesz to tylko do warstwy prezentacji (tylko do wyświetlania sekwencji) np do pokazania wykresu to przetrzymywanie tej wartości w bazie nie ma sensu. Natomiast jeżeli chcesz w miarę szybko wyszukiwać po tej wartości np. odszukać wszystkie dni gdzie był spadek/wzrost to może warto byłoby to trzymać. ale osobiście zrobiłbym do tego jakąś osobną tabelę żeby nie zaciemniać sobie obrazu właściwych danych. Dodatkowo musisz pamiętać, że dane z dodatkowej tablicy przestaną być aktualne jeżeli zmienisz coś we właściwych danych. Wtedy należy pamiętać o dwóch update'ach smile.gif


-- edit

Myślę, że mógłbyś jeszcze utworzyć dodatkową kolumnę z identyfikatorem dnia poprzedniego np:

Kod
id_dzien, wartosc, id_dzien_poprzedni
1    10    NULL
2    13    1
3    5    2


id_dzien_poprzedni dać jako klucz obcy (id_dzien) i wtedy możesz sobie łączyć dane zwykłym joinem, liczyć średnie, wyszukiwać dni ze zyskiem/stratą

Ten post edytował ghost1511 21.02.2014, 11:31:51
Go to the top of the page
+Quote Post
phpion
post 21.02.2014, 11:33:05
Post #6





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




Po co ta dodatkowa kolumna? Przecież to wszystko można w SQL policzyć. Fakt, jeśli mogą być luki i istnieje nas poprzedni wpis (niekoniecznie poprzedni dzień) wówczas na pewno przyspieszy to zapytanie zasugerowane przeze mnie. Logiczniejsze dla mnie jednak jest bazowanie na dniu poprzednim, a nie poprzedniej wartości.

PS: Żeby móc JOINować wcale nie trzeba zakładać klucza obcego. W tym przypadku należałoby go jednak założyć, ale z racji integralności danych, a nie możliwości/niemożliwości wykonywania złączeń.
Go to the top of the page
+Quote Post
ghost1511
post 21.02.2014, 11:35:22
Post #7





Grupa: Zarejestrowani
Postów: 186
Pomógł: 18
Dołączył: 2.09.2010

Ostrzeżenie: (0%)
-----


Tak tak smile.gif ja podałem rozwiązanie dla przypadku z lukami w czasie. Tak jest np z kursem walut i szczerze mówiąc domyślam się, że tego dotyczy ten przypadek.
Go to the top of the page
+Quote Post
phpion
post 21.02.2014, 11:41:36
Post #8





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




Ja bym zadbał o to by mieć dane na każdy dzień i zrobił to tak:
  1. CREATE TABLE `test` (
  2. `date` DATE NOT NULL ,
  3. `value` INT NOT NULL ,
  4. PRIMARY KEY (`date`) );
  5.  
  6. INSERT INTO `test` (`date`, `value`) VALUES
  7. ('2014-02-18', 10),
  8. ('2014-02-19', 22),
  9. ('2014-02-20', 31),
  10. ('2014-02-21', 44)
  11. ;
  12.  
  13. SELECT
  14. cur.date,
  15. cur.value,
  16. (CASE WHEN prev.value IS NOT NULL THEN cur.value - prev.value ELSE NULL END) AS diff
  17. FROM
  18. test AS cur
  19. LEFT JOIN test AS prev ON (prev.date = DATE_SUB(cur.date, INTERVAL 1 DAY))
  20. ORDER BY
  21. cur.date ASC
  22. ;
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 18.06.2025 - 11:16