Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Problem ze złożonymi zapytaniami i podzapytaniami
Helios
post
Post #1





Grupa: Zarejestrowani
Postów: 24
Pomógł: 0
Dołączył: 8.07.2006

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


Witam

Mam problem z napisaniem zapytania do bazy MySQL. Mecze sie z tym juz 2 dni i nie widac konca.

Mam 2 tabele zawierajace wpisy uzytkownikow:

Articles (Id, AuthorId, Votes, Rate)
Texts (Id, AuthorId, Votes, Rate)

Pole AuthorId to odeslanie do Id z tabeli uzytkownikow. Pola Votes, Rate mam do wyliczania sredniej ocen oddanych na te publikacje obliczam przez zaokraglenie Rate/Votes (przy glosowaniu zwiekszam Votes o 1 i dodaje ocene do Rate).

Moj problem polega na tym, ze w jednym zapytaniu chce:

- chce pobrac dane z tabeli uzytkownika (Id, Login, etc.)
- posortowac uzytkownikow ze wzgledu na srednia dodanych przez nich publikacji (srednia razem z obu tabel)
- zbior wynikow ograniczyc tylko do tych uzytkownikow, ktorzy maja co najmniej 5 publikacji (obojetnie z ktorej tabeli)

Czyli staram sie wykombinowac cos w stylu:

  1. SELECT
  2. Users.Id, Users.Login,
  3. (SELECT SUM(Articles.Rate) FROM Articles WHERE Articles.AuthorId=Users.Id) AS ArtRate,
  4. (SELECT SUM(Articles.Votes) FROM Articles WHERE Articles.AuthorId=Users.Id) AS ArtVotes,
  5. (SELECT SUM(Texts.Rate) FROM Texts WHERE Texts.AuthorId=Users.Id) AS TxtRate,
  6. (SELECT SUM(Texts.Votes) FROM Texts WHERE Texts.AuthorId=Users.Id) AS TxtVotes
  7. FROM (SELECT Users.Id, Users.Login FROM Users WHERE (SELECT COUNT(*) FROM Articles WHERE Articles.AuthorId=Users.Id)>5 OR (SELECT COUNT(*) FROM Texts WHERE Texts.AuthorId=Users.Id)>5) AS Users
  8. ORDER BY ((ArtRate+TxtRate)/(ArtVotes+TxtVotes))


No i nie dziala i wiele innych kombinacji podobnego kodu tez nie dziala. ORDER BY nie widzi tak jakby tych pobranych pol.

Czy ktos moze mi pomoc, ewentualnie podeslac linka do jakiejs publikacji gdzie znajde informacje na temat popelnianego bledu?

Z gory dzieki!

Pozdrawiam
Go to the top of the page
+Quote Post
phpion
post
Post #2





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




Problem leży pewnie w tym, że w klauzuli ORDER BY stosujesz aliasy kolumn, a z tego co się orientuję takie coś nie przejdzie. Nie wiem czy we wszystkich wersjach MySQL tak nadal jest ale wcześniej taki problem występował. Poza tym - w Twoim przypadku zdecydowanie lepiej złamać postać normalną i mimo wszystko wejść w redundację danych. Ja bym utworzył osobne kolumny w tabeli, które będą przechowywać wartości, które aktualnie obliczasz podzapytaniami. Dodatkowo należałoby odpalić triggera na wszystkich operacjach (INSERT, UPDATE, DELETE) aktualizującego pola dla danego rekordu. Wydajność powinna zwiększyć się znacząco i unikniesz problemów z ORDER BY.
Go to the top of the page
+Quote Post
Helios
post
Post #3





Grupa: Zarejestrowani
Postów: 24
Pomógł: 0
Dołączył: 8.07.2006

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


Hm, nie wiem czy dobrze zrozumialem Twoje intencje, ale u mnie chyba to nie przejdzie, gdyz opisany problem to tylko jeden z wielu. Pozniej bede musial prowadzic statystyki i sortowac uzytkownikow z najwyzsza srednia publikacji wg. daty ich dodania. Czyli np. statystyki uzytkownikow z najwyzszymi srednimi za miesiac 02/2008.
Moze ma ktos jeszcze jakies pomysly. Skoro nie moge stosowac aliasow to jak to rozwiazac?
Go to the top of the page
+Quote Post
nevt
post
Post #4





Grupa: Przyjaciele php.pl
Postów: 1 595
Pomógł: 282
Dołączył: 24.09.2007
Skąd: Reda, Pomorskie.

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


Cytat
Problem leży pewnie w tym, że w klauzuli ORDER BY stosujesz aliasy kolumn, a z tego co się orientuję takie coś nie przejdzie.
Jeżeli MySQL ver > 5.0 to nieprawda - aliasy przejdą ....
Cytat
No i nie dziala i wiele innych kombinacji podobnego kodu tez nie dziala. ORDER BY nie widzi tak jakby tych pobranych pol.

Czyli zapytanie działa (wyświetla ci prawidłowe dane) tylko źle posortowane?
Czy całe zapytanie jest do niczego (skąd zatem wiesz, że ORDER BY nie działa)?
Tak czy inaczej, ja bym spróbował czegoś w rodzaju (piszę z pamięci, więc wybacz ew. potknięcia):
  1. SELECT Users.Id, Users.Login, COUNT(Articles.Id) AS ArtCnt, SUM(Articles.Rate) AS ArtRate, SUM(Articles.Votes) AS ArtVotes, COUNT(Texts.Id) AS TxtCnt, SUM(Texts.Rate) AS TxtRate, SUM(Texts.Votes) AS TxtVotes FROM Users LEFT JOIN Articles ON Users.Id = Articles.AuthorId LEFT JOIN Texts ON Users.Id = Texts.Author.Id GROUP BY Users.Id WHERE (ArtCnt + TxtCnt) > 5 ORDER BY ((ArtRate + TxtRate) / (ArtVotes + TxtVotes));


Ten post edytował nevt 19.02.2008, 15:10:24
Go to the top of the page
+Quote Post
Helios
post
Post #5





Grupa: Zarejestrowani
Postów: 24
Pomógł: 0
Dołączył: 8.07.2006

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


Ok, poradzilem sobie z tym. Wniosek z tego, ze moj problem polegal na tym, ze wykorzystywalem aliasy w WHERE i ORDER BY, wiec podzapytania musialem przerzucic bezposrednio w te klauzule. Dodatkowo MySQL nie wyliczal mi poprawnie sredniej, gdyz w niektorych publikacjach liczba glosow i srednia byly rowne 0 i MySQL zwracal NULL, a ciekawy test SELECT 1+NULL dal mi wartosc NULL i tak o to wpadlem na takie rozwiazanie:

  1. SELECT
  2. Users.Id, Users.Name,
  3. IFNULL(ROUND((SELECT SUM(Articles.Rate)/SUM(Articles.Votes) FROM Articles WHERE Articles.AuthorId=Users.Id), 2),0.00) AS ArticlesRate,
  4. IFNULL(ROUND((SELECT SUM(Texts.Rate)/SUM(Texts.Votes) FROM Texts WHERE Texts.AuthorId=Users.Id), 2),0.00) AS TextsRate
  5. FROM Users WHERE ((SELECT COUNT(*) FROM Articles WHERE Articles.AuthorId=Users.Id)+(SELECT COUNT(*) FROM Texts WHERE Texts.AuthorId=Users.Id))>=2
  6. ORDER BY (IFNULL((SELECT SUM(Articles.Rate) FROM Articles WHERE Articles.AuthorId=Users.Id),0)+IFNULL((SELECT SUM(Texts.Rate) FROM Texts WHERE Texts.AuthorId=Users.Id),0))
  7. /
  8. (IFNULL((SELECT SUM(Articles.Votes) FROM Articles WHERE Articles.AuthorId=Users.Id),0)+IFNULL((SELECT SUM(Texts.Votes) FROM Texts WHERE Texts.AuthorId=Users.Id),0))
  9. DESC


No i tak na marginesie, wybranie uzytkownikow i posortowanie wg. aktywnosci (ilosc publikacji w ciagu dnia od dnia rejestracji):

  1. SELECT
  2. Users.Id, Users.Name,
  3. ROUND((SELECT COUNT(*) FROM Articles WHERE Articles.AuthorId=Users.Id)/DATEDIFF(CURRENT_DATE(), Users.RegistrationDate),2) AS ArticlesPerDay,
  4. ROUND((SELECT COUNT(*) FROM Texts WHERE Texts.AuthorId=Users.Id)/DATEDIFF(CURRENT_DATE(), Users.RegistrationDate),2) AS TextsPerDay
  5. FROM Users ORDER BY
  6. ROUND(((SELECT COUNT(*) FROM Articles WHERE Articles.AuthorId=Users.Id)+(SELECT COUNT(*) FROM Texts WHERE Texts.AuthorId=Users.Id))/DATEDIFF(CURRENT_DATE(), Users.RegistrationDate),2) DESC


Pozdrawiam

Ten post edytował Helios 19.02.2008, 16:14:02
Go to the top of the page
+Quote Post

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

 



RSS Aktualny czas: 22.08.2025 - 17:21