Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Trigger, wyzwalacze, Czyli jak ograniczyć ilość zapytań
Fifi209
post 22.04.2011, 22:30:44
Post #1





Grupa: Zarejestrowani
Postów: 4 655
Pomógł: 556
Dołączył: 17.03.2009
Skąd: Katowice

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


Witam, stanąłem przed następującym problemem, przebudowuję stronę kumpla, jego baza danych była bardzo nieoptymalnie zaprojektowana (nadmiarowość danych) etc.
Postawiliśmy ją przeprojektować, co zmusiło mnie do utworzenia nowej o zupełnie innej strukturze.

Projekt to ogólnie fansite, który zajmuje się gromadzeniem danych o graczach.
Usługodawca hostingu, poprosił o zmniejszenie liczby zapytań - stąd nowa baza i pytanie, które chcę zadać.

Przykładowe dwie powiązane tabele:

Players:
id, nick

Online:
id, player_id, time, online

Tabela online przechowuje dzienne zestawienia dla gracza ile godzin był online.
time - data
online - czas w minutach przez jaki grał

Teraz chciałbym za jednym zapytaniem zrobić następujące rzeczy;
  • Sprawdzić czy gracz istnieje w players, jeżeli nie to go dodać i pobrać id
  • Sprawdzić czy w dniu dzisiejszym został dodany rekord, jeżeli tak to dodać czas jeżeli nie to najpierw zrobić insert do tabeli online


I teraz moje pytanie, czy da się to zrobić jednym zapytaniem?


--------------------
Zainteresowania: C#, PHP, JS, SQL, AJAX, XML, C dla AVR
Chętnie pomogę, lecz zanim napiszesz: Wujek Google , Manual PHP
Go to the top of the page
+Quote Post
pmir13
post 23.04.2011, 00:37:41
Post #2





Grupa: Zarejestrowani
Postów: 282
Pomógł: 89
Dołączył: 12.04.2011

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


Rozumiem że pytasz czy każdą z tych czynności da się zrobić jednym zapytaniem. Bo trudno jest mi sobie wyobrazić zapytanie, które robiłoby to wszystko naraz. Chyba że jest to zapytanie typu wywołanie procedury.

Co do pierwszego - jeżeli w tabeli masz tylko te dwa pola to nie widzę możliwości zrobienia tego w jednym zapytaniu, jeśli jednak byłoby coś więcej to z pewnością dałoby się to zrobić. Na przykład gdyby było dodane pole ostatnio typu datetime można byłoby wykorzystywać:
  1. INSERT INTO players(nick,ostatnio) VALUES('tester',now()) ON duplicate KEY UPDATE ostatnio=now();

Oczywiście by to działało musi być ustawiony klucz primary na id i unique na nick. Wtedy last_insert_id ustawiany jest na id wstawionego rekordu niezależnie od tego czy został wykonany insert czy update. Gdyby jednak nie było pola ostatnio, musielibyśmy stosować albo dwa zapytania - insert+select, albo insert ignore, który nie zwraca last_insert_id w przypadku próby powtórzenia klucza unique, albo obejście składniowe w stylu on duplicate key update id=id, które też by nie zwracało last_insert_id gdyby podany nick już w bazie był, bo żadna realna zmiana w rekordzie by nie zaszła i nic do zmiany byśmy nie mieli. Być może jakiś sposób istnieje by to zmieścić w jednym zapytaniu bez dodatkowego pola i jednocześnie dostać id, ale ja go nie znam.

Co do drugiego to sprawa jest prostsza, bo taką dodatkową kolumną jest czas online, który będziemy zwiększać. Czyli klucz unique na parę ( player_id, dzien ) i jeśli chcemy graczowi tester dodać 30 minut to zapytanie
  1. INSERT INTO online( player_id, dzien, czas_online ) VALUES ( 1, date(now()), 30 ) ON duplicate KEY UPDATE czas_online = czas_online + 30;

Zmieniłem tutaj trochę nazwy kolumn by time nie myliło się z funkcją time, a kolumna online z nazwą tabeli online.
Go to the top of the page
+Quote Post
Fifi209
post 25.04.2011, 19:17:30
Post #3





Grupa: Zarejestrowani
Postów: 4 655
Pomógł: 556
Dołączył: 17.03.2009
Skąd: Katowice

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


Zrobiłem na funkcjach i działa tak jak chciałem smile.gif
Problem rozwiązany, natchnąłeś mnie procedurami.


--------------------
Zainteresowania: C#, PHP, JS, SQL, AJAX, XML, C dla AVR
Chętnie pomogę, lecz zanim napiszesz: Wujek Google , Manual PHP
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: 22.06.2025 - 06:28