MySQL: DISTINCT 2 rows...
 
Lucifix 20. nov 2012 12:23:05 Pridružen od:
14. okt 2008
744 objav
438 12 0
#1

Če se mi kdaj zaplete pri programiranju, pa je to pri kakšnem bolj zahtevnem MySQL stavku in zato vas prosim za pomoč.



Imam tabelo zasebna_sporocila, ki ima takšno strukturo:



id | fromuser | touser | message | date

1 | 1 | 3 | blablabla | 1043684100

2 | 1 | 2 | blablabla | 1049146320

3 | 2 | 1 | blablabla | 1049146920

4 | 3 | 1 | blablabla | 1049147100

5 | 2 | 3 | blablabla | 1049153340

6 | 1 | 2 | blablabla | 1049627280



Z navadnim DISTINCT ukazom (SELECT DISTINCT fromuser, touser FROM zasebna_sporocila) dobim takšen rezultat:



fromuser | touser

1 | 3

1 | 2

2 | 1

3 | 1

2 | 3



Problem pa je, ker bi rad dobil unikatne poizvedbe. V zgornjem rezultatu se prikaže 1 2 in 2 1 - kar bi želel, da se prikaže kot en rezultat, saj bi rad dobil zgrupirana sporočila med dvema uporabnikoma. Nekako podobno kot ima to narejeno Facebook v zasebnih sporočilih.



Nekam bi moral še dodati poizvedbo WHERE (fromuser = 1 OR touser = 1) - rezultat za uporabnika, ki ima id 1.



Seveda moram potem na koncu rezultate urediti po datumu (ORDER BY date DESC).



Kakršnakoli pomoč več kot dobrodošla! Zakomplicirano? :)


všeč(0) ni všeč(0) spam(0)
 
Mešetar 20. nov 2012 12:38:34 Pridružen od:
24. nov 2010
1543 objav
1945 962 114
#2

poglej za GROUP BY, v tvojem primeru pred ORDER BY das GROUP BY(to_user) verjetno


všeč(0) ni všeč(0) spam(0)
 
boskor 20. nov 2012 12:47:08 Pridružen od:
14. sep 2011
18 objav
7 1 0
#3

probaj s tem:



SELECT *

FROM zasebnasporocila

WHERE (sender
id=$id1 OR receiverid=$id1)

AND (sender
id=$id2 OR receiver_id=$id2)

ORDER BY date


všeč(0) ni všeč(1) spam(0)
 
Lucifix 20. nov 2012 12:54:14 Pridružen od:
14. okt 2008
744 objav
438 12 0
#4

@boskar tvoj primeru bi prišel prav, če bi že imel id od ostalih članov s katerimi je dotični član izmenjal sporočila. Jaz pa želim dobiti vsa ID sporočila, v katerih je sodeloval en uporabnik (npr. id = 1). Problem pa je, ker ima lahko taisti uporabnik (id = 1) svoj id vpisan v row fromuser ali pa touser.



@Mešetar mislim, da mi group by ne bo prišel prav...


všeč(0) ni všeč(0) spam(0)
 
Vini 20. nov 2012 12:54:22 Pridružen od:
1. sep 2006
6612 objav
5234 611 56
#5

Takšne poizvedbe nikoli ne boš mogel zadovoljivo optimizirati in bo po vsej verjetnosti trajala preveč časa in ti s tem ubijala strežnik, ko boš imel teh sporočil več. Jaz bi na tvojem mestu dodal še eno tabelo, ki bi vsebovala ID uporabnika, ID sporočila, mogoče še timestamp sporočila, da bo tudi ORDER BY lahko uporabil indeks. V to tabelo ob dodajanju vsakega sporočila dodaš dva zapisa, v enega zapišeš ID od fromuser, v drugega ID od touser, v oba pa isti ID sporočila in isti timestamp.



Tole dodajanje dveh zapisov lahko tudi avtomatiziraš z uporabo triggerjev.



Poizvedba je potem enostavna:


SELECT
zasebna_sporocila.*
FROM
zasebna_sporocila_pomozna,
zasebna_sporocila
WHERE
zasebna_sporocila_pomozna.user_id = 1 AND
zasebna_sporocila.id = zasebna_sporocila_pomozna.sporocilo_id
ORDER BY
zasebna_sporocila_pomozna.datum;

Če v tabeli zasebnasporocilapomozna nastavis indeks na polji user_id in datum, ga bo ta poizvedba tudi uporabila in bo zato tudi seveda super hitra. :)


všeč(7) ni všeč(0) spam(0)
 
Vini 20. nov 2012 12:59:31 Pridružen od:
1. sep 2006
6612 objav
5234 611 56
#6

Če mogoče ni najbolj jasno zakaj je tu potreben tudi indeks na polju datum, sem o tem nekoč davno pisal na svojem sicer že davno mrtvem blogu, pa da se ne ponavljam, je tukaj kar link: SQL in indeksi (2.del)


všeč(0) ni všeč(0) spam(0)
 
Mešetar 20. nov 2012 12:59:40 Pridružen od:
24. nov 2010
1543 objav
1945 962 114
#7

v tem primeru naredis vedno 2 poizvedbe, ena za FROM users, druga za TO user.... in jih groupiras poo menjenih indexih...



ni mi pa jasno, kaj je tvoj namen?



ce bi rad to delal s sporocili, bi moral voditi idsporocila (root) in potem vsa pripeta sporocila k temu (parentid) ... ce gre za sporocila tipa pri FBju ... ali forumu (ali gmailu)...



ce gre za normalen chat pa je zadosti where fromid = 1 OR fromid=2 OR toid=1 OR toid=2


všeč(0) ni všeč(0) spam(0)
 
Lucifix 20. nov 2012 13:15:19 Pridružen od:
14. okt 2008
744 objav
438 12 0
#8

@Vini mogoče je tvoja rešitev res najbolj primerna. Bolj me skrbi, da bom moral potem preurejati še ostalo kodo, da bo v primeru izbrisa uporabnika ali pa izbrisa kakšnega sporočila potrebno narediti tudi en nov sql stavek, ki bo urejat tisto pomožno tabelo.

Navsezadnje mi je pomembno le da dobim zadnji ID tabele, ki sta je 2 uporabnika uporabljala za chat.



@Mešetar




ce bi rad to delal s sporocili, bi moral voditi idsporocila (root) in potem vsa pripeta sporocila k temu (parentid) ... ce gre za sporocila tipa pri FBju ... ali forumu (ali gmailu)...




To pa je predlagal Vini v svojem postu - če sem te prav razumel.


všeč(0) ni všeč(0) spam(0)
 
Vini 20. nov 2012 13:17:23 Pridružen od:
1. sep 2006
6612 objav
5234 611 56
#9

Lucifix, tudi brisanje sporočila in hkratno brisanje zapisov v pomožni tabeli lahko urediš s triggerji.


všeč(0) ni všeč(0) spam(0)
 
Lucifix 20. nov 2012 13:21:02 Pridružen od:
14. okt 2008
744 objav
438 12 0
#10

Thx Vini, grem na delo, ker bo to verjetno kar dobra rešitev ;)


všeč(0) ni všeč(0) spam(0)
 
 

🔒 Za odgovor na to temo se moraš prijaviti.

Prijavi se