Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [SQL] where i funkcja max
Forum PHP.pl > Forum > Przedszkole
peter13135
  1. SELECT f. * , t.name AS lt_name, t.id AS lt_id
  2. FROM `laczekbb_forums` f
  3. LEFT JOIN `laczekbb_topics` t ON f.id = t.forum
  4. WHERE t.id = max( t.id )
  5. GROUP BY f.id ASC
  6. ORDER BY f.cat ASC , f.id ASC


omówienie zapytania:
zapytanie ma za zadanie pobierać fora oraz ostatni temat w danym forum
tabela `laczekbb_forums` to poprostu fora/kategorie forum
tabela `laczekbb_topics` to tematy które są uporządkowane w tych kategoriach
t.forum - to id forum w jakim znajduje się temat

problem polega na tym że po dodaniu
  1. WHERE t.id = max( t.id )

zapytanie nie działa,

w jaki sposob mogę osiągnąć to że do tych for "doklejany" jest temat o najwyższym id w danej kategorii ?

czyli jeśli mam 3 tematy w konkretnym forum, i mają kolejo id 1,43,678 to żeby mi wybrało ten z id 678. Dodam że dodanie Order by t.id DESC nie pomoga


PS. no właściwie to wolałbym po dacie a nie po id, ale to już sobie poradzę żeby to przerobić
jacusek
Nie wiem czy to coś pomoże, ale może spróbuj dodać coś takiego:
  1. WHERE t.id = select max( t.id ) from twoja_tablica

Mnie kiedyś coś takiego pomogło.
blooregard
Cytat
Nie wiem czy to coś pomoże, ale może spróbuj dodać coś takiego:

Pomoże. To są tzw. podzapytania. Tylko pamiętaj o zapisaniu go w nawiasach:
  1. WHERE t.id = (SELECT max( t.id ) FROM twoja_tablica)


Poza tym podzapytania sa bardzo obciążającą wydajnościowo konstrukcją SQL-a. Jeśli możesz, postaraj się najpierw zwykłym SELECT-em wyciągnąć ten max(t.id), a potem wstawić go do właściwego zapytania jako zmienną.
peter13135
max(t.id) jest inny dla kazdego forum, wiec chyba to nie bedzie takie proste... czy niema innego sposobu questionmark.gif wydaje mi sie ze to prosta sprawa, moze cos z sortowaniem ?
thomson89
jezeli każde id jest 'następne po sobie', sortujesz odwrotnie i pobierasz id pierwszego wiersza
bolverk
Kod
SELECT f. * , t.name AS lt_name, t.id AS lt_id
FROM `laczekbb_forums` f
LEFT JOIN `laczekbb_topics` t ON f.id = t.forum
WHERE t.id = max( t.id )
GROUP BY f.id ASC
ORDER BY f.cat ASC , f.id ASC


Dla mnie w tym zapytaniu zwróciło uwagę odwoływanie się do aliasów. Zazwyczaj odwoływanie się do aliasów następuje po wyrażeniu FROM, np:
Kod
select c1.name, c2.name, c1.city
from customers as c1, customers as c2
where c1.city = c2.city


A w Twoim zapytaniu odwołanie do aliasów następuje przed wyrażeniem FROM. Można by mnie osądzić o małą wiedzę na temat składni SQL, ale czy aliasy nie powinny być po wyrażeniu FROM? Jeśli nie mam racji to proszę o poprawienie mnie smile.gif
peter13135
bolverk - przykro mi ale cię kompletnie nie rozumiem

thomson89 niewiem czy masz racje bo tak średnio cię rozumiem, masz na myśli żeby pobrać najpierw to maxymalne id i potem je wstawić do zapytania questionmark.gif jeśli tak, to proszę pokaż mi jak to zrobić. Problem polega na tym że do każdy temat jest w jakimś konkretnym forum, dla każdego forum temat o maxymalnym id jest inny. dla przykładu dla forum 1 są tematy o id 1,3,8, a dla forum 2 są tematy o id 2,4,5, dla dla forum 3 są tematy o id 6,7,9
więc :
forum - ostatni id temat
1 - 8
2 - 5
3 - 9


chyba nie możliwe jest wyciągnięcie tego id wcześniej i wstawienie do zapytania, chyba że macie coś na myśli czego ja nie rozumiem

EDIT://

SELECT f. * , t.name AS lt_name, t.id AS lt_id
FROM `laczekbb_forums` f
LEFT JOIN `laczekbb_topics` t ON f.id = t.forum
WHERE t.id = (
SELECT max( id )
FROM `laczekbb_topics`
WHERE forum = f.id )
GROUP BY f.id ASC

zrobiłem tak, i jakoś działa, troche wolniej, więc nie wiem jak to będzie działało przy większej liczy rekordów, ale póki co to najlepsze rozwiązaenie jakie znam
thek
A czemu nikt nie pomyślał o właściwym order by? winksmiley.jpg Skoro łączymy fora i tematy to tam już musimy przesłać tematy uporządkowane od najwyższego i dopiero grupować po id_forum. To sprawi, że dostaniemy tę strukturę o jaką chodzi... W najprostszej postaci jaką opisałem (niekoniecznie optymalnej) to byłoby:
  1. SELECT * FROM (SELECT f.id AS forum, t.id AS topic FROM forums f LEFT JOIN topics t ON f.id = t.forum ORDER BY f.id ASC, t.id DESC) GROUP BY forum
Czy coś w tym stylu smile.gif Piszę z palca bo nie mam serwera MysQL na kompie dziewczyny zainstalowanego. Jedyny byk jaki może wyniknąć to taki, że całe to za FROM podzapytanie zwróci error, iż brak mu aliasu smile.gif Wtedy tylko minimalna zmiana i powinno hulać.

EDIT: Ja wyciągnąłem jedynie id forum i id tematu najwyższego. Ty możesz dopisać więcej kolumn.
peter13135
  1. SELECT f. * , t.name AS lt_name, t.id AS lt_id
  2. FROM `laczekbb_forums` f
  3. LEFT JOIN `laczekbb_topics` t ON f.id = t.forum
  4. WHERE t.id = (
  5. SELECT max( id )
  6. FROM `laczekbb_topics`
  7. WHERE forum = f.id )
  8. GROUP BY f.id ASC


jak wcześniej pisałem takie coś działa... ale tylko wtedy kiedy w forum istnieje temat, jeśli w danym forum niema ani jednego tematu to poprostu nie zwróci rekordu, co trzeba zrobić aby w przypadku braku tematów w forum pola pola lt_id oraz lt_name były poprostu zwracane jako puste ?

PS. w tabeli forums znajduje się kolumna o nazwie `topics` której zawartość to liczba tematów, może się to przyda

napisałem tak

  1. SELECT f. * , t.name AS lt_name, t.id AS lt_id
  2. FROM `laczekbb_forums` f
  3. LEFT JOIN `laczekbb_topics` t ON t.id = (
  4. SELECT max( id )
  5. FROM laczekbb_topics
  6. WHERE forum = f.id )
  7. GROUP BY f.id


i wydaje sie działać poprawnie
thek
Widzę, że nawet nie sprawdziłeś czy zapytanie jakie Ci podałem działa! Dorwałem się do swojego kompa i założyłem 2 tabele:
FORUM
id nazwa
1 Pierwsze
2 Drugie
3 Trzecie
4 Czwarte

TOPIC
id forum_id nazwa
1 1 Jeden
2 1 Dwa
3 1 Trzy
4 3 Cztery
5 3 Pięć
6 3 Sześć
7 4 Siedem
8 4 Osiem

Zauważ, że forum o id = 2 nie ma topiców żadnych... Teraz zapytanie:
  1. SELECT * FROM (SELECT f.id AS forum, f.nazwa AS nazwa_forum, t.id AS topic_id FROM forum f LEFT JOIN topic t ON f.id = t.forum_id ORDER BY f.id ASC, t.id DESC) a GROUP BY a.forum

i w efekcie dostałem...
forum nazwa_forum topic_id
1 Pierwsze 3
2 Drugie NULL
3 Trzecie 6
4 Czwarte 8
Czy było to tak trudno sprawdzić?

Co lepsze... Minimalna zmiana i nawet LEFT JOIN wystarczył:
  1. SELECT f.id AS forum, f.nazwa AS nazwa_forum, max(t.id) AS topic_id FROM forum f LEFT JOIN topic t ON f.id = t.forum_id GROUP BY f.id


EDIT: Twoje selecty i join zostały skrócone do jednego LEFT JOIN i grupowania smile.gif Wystarczy teraz jedynie sprawdzać, czy topic_id jest równe NULL. Jeśli tak to znaczy, że forum nie posiada tematów.

EDIT2: Zerknąłem na stronę MySQL.... Tam przykład z LEFT JOIN jest nawet w przykładach sciana.gif
http://dev.mysql.com/doc/refman/5.1/en/exa...lumn-group.html
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.