Avatar billede bmdk Nybegynder
09. august 2009 - 22:53 Der er 14 kommentarer og
1 løsning

Select problem

Hey alle!

Sidder i øjeblikket med en SQL sætning der gør lidt vrøvl for mig.

Jeg har intet mindre end 4 tabeller, der skal hentes data ud fra.
For at gøre det hele lidt lettere for jer at tyde, har jeg lige taget screenshot af mine tabeller.

Screenshot: http://www.bo-mortensen.dk/table.jpg

Det jeg gerne vil er, at hente følgende ud:

tab.*
comment.* hvor tabId = tab.id
comment_member.cUsername hvor comment_member.id = comment.id
tab_rating.rating hvor tab_rating.tabId = tab.id

Allerede der har jeg jo egentlig skrevet pseudokoden til min select sætning og jeg har også fået hevet data ud med følgende SQL sætning:

SELECT DISTINCT tab.*, tab_rating.rating, comment.*, comment_member.commentId, comment_member.cUsername FROM tab, tab_rating, comment, comment_member WHERE tab.id = '$tabId' AND comment.tabId = '$tabId' AND comment_member.commentId = comment.id AND tab_rating.tabId = '$tabId' (taget fra mit php script)

Mit problem er bare, at hvis et tab endnu ikke er bedømt/rated og tab_rating tabellen er tom, så henter den slet ikke nogle data fra nogle tabeller. Er der nogen måde man kan gøre det på?
Er ikke den stærkeste i SQL, så hvis nogen kan regne denne ud ville det være for fedt! :)

På forhånd tak.

Mvh. Bo
Avatar billede bmdk Nybegynder
09. august 2009 - 22:54 #1
Øh, og samme problemstilling gør sig jo gældende hvis der endnu ikke er skrevet nogle kommentarer til et tab..
Avatar billede arne_v Ekspert
09. august 2009 - 23:40 #2
Du må skulle erstatte dine implicitte joins med LEFT JOIN's !
Avatar billede arne_v Ekspert
09. august 2009 - 23:41 #3
SELECT * FROM t1,t2 WHERE t1.x = t2.x AND t1.y = 77

og

SELECT * FROM t1 JOIN t2 ON t1.x = t2.x WHERE t1.y = 77

vælger kun data hvis de eksisterer i både t1 og t2.

SELECT * FROM t1 LEFT JOIN t2 ON t1.x = t2.x WHERE t1.y = 77

tager derimod data fra t1 uanset om der er matchende data i t2 eller ej.
Avatar billede bmdk Nybegynder
09. august 2009 - 23:56 #4
takker for dit svar arne_v!

Kan godt se hvad du siger mht at bruge left join, men det roder godt nok lidt rundt i hovedet på mig i øjeblikket.

Du skriver: SELECT * FROM t1 LEFT JOIN t2 ON t1.x = t2.x WHERE t1.y = 77

Dvs for mit vedkommende er det:

SELECT * FROM comment LEFT JOIN comment_member ON comment.id = comment_member.commentId AND comment.tabId = tab.id AND tab.id = tab_rating.tabId

? .. er vist helt ude af den her ;) godt nok besværligt når det er over 4 tabeller man skal hive data ud synes jeg!
Avatar billede bmdk Nybegynder
09. august 2009 - 23:57 #5
.. mente selvfølgelig:

SELECT * FROM comment LEFT JOIN comment_member ON comment.id = comment_member.commentId AND comment.tabId = tab.id AND tab_rating.tabId = 1


Men det giver intet..
Avatar billede arne_v Ekspert
10. august 2009 - 00:16 #6
Hm.

tab_rating tabellen er slet ikke i FROM listen for den query, så den giver vel en syntax fejl.
Avatar billede bmdk Nybegynder
10. august 2009 - 00:23 #7
Ah, ja det gjorde den også - og med samme fejl som du siger :) den er ikke med i FROM listen..

Har forsøgt mig med:

SELECT * FROM tab, tab_rating, comment, comment_member
JOIN comment ON comment.tabId = tab.id
JOIN comment_member ON comment_member.commentId = comment.id
JOIN tab_rating ON tab_rating.tabId = tab.id
WHERE tab.id = 1

.. men får fejlen: Not unique table/alias: 'comment'
Avatar billede bmdk Nybegynder
10. august 2009 - 00:27 #8
kan se den skriver error output ud med "COMMENT" - er det reserved eller noget?

Error output:

SELECT *
FROM tab, tab_rating,
COMMENT , comment_member
JOIN COMMENT ON comment.tabId = tab.id
JOIN comment_member ON comment_member.commentId = comment.id
JOIN tab_rating ON tab_rating.tabId = tab.id
WHERE tab.id =1
LIMIT 0 , 30
Avatar billede bmdk Nybegynder
10. august 2009 - 00:50 #9
Yessir!! Så fik jeg den sgu til at kaste det rigtige ud! :)

Løsning:

SELECT tab.instrument, tab.tabtext, tab.date, tab.artist, tab.songtitle, tab.username, comment.commenttext, comment.cDate, comment_member.cUsername, tab_rating.rating FROM tab LEFT JOIN comment ON comment.tabId = tab.id LEFT JOIN comment_member ON comment.id = comment_member.commentId LEFT JOIN tab_rating ON tab.id = tab_rating.tabId


arne_v, smider du et svar? :)
Avatar billede arne_v Ekspert
10. august 2009 - 00:55 #10
Kommer her.

Jeg ville skrive queryen som:

SELECT tab.instrument, tab.tabtext, tab.date, tab.artist, tab.songtitle, tab.username, comment.commenttext, comment.cDate, comment_member.cUsername, tab_rating.rating
FROM ((tab LEFT JOIN comment ON comment.tabId = tab.id)
    LEFT JOIN comment_member ON comment.id = comment_member.commentId)
    LEFT JOIN tab_rating ON tab.id = tab_rating.tabId

for at gøre den nemmere at læse.
Avatar billede bmdk Nybegynder
10. august 2009 - 01:16 #11
Jeg takker mange gange :)

Jeg har dog et enkelt lille problem mere.. ved brug af:

SELECT tab.instrument, tab.tabtext, tab.date, tab.artist, tab.songtitle, tab.username, comment.commenttext, comment.cDate, comment_member.cUsername, tab_rating.rating
FROM ((tab LEFT JOIN comment ON comment.tabId = tab.id)
    LEFT JOIN comment_member ON comment.id = comment_member.commentId)
    LEFT JOIN tab_rating ON tab.id = tab_rating.tabId WHERE tab.id = 1

Får jeg resultatet to gange.. er der ikke en måde hvorpå jeg bare får resultatet 1 gang? :) har prøvet lidt frem med LIMIT, men det går jo ikke, så skal jeg altid vide hvor mange rækker jeg præcist vil have ud jo..
Avatar billede arne_v Ekspert
10. august 2009 - 01:47 #12
Det gør du vel også med varianten i #9.

Der må være en af tabellerne som har to rækker for hver række du vil have.

Måske skal den tabel ikke med. Måske skal du bruge DISTINCT. Måske skal du bruge GROUP BY.
Avatar billede bmdk Nybegynder
10. august 2009 - 01:55 #13
Problemet er, at der kan være flere comment-rækker end der kan være rating-rækker eller omvendt.. så hvis jeg vælger GROUP BY comment.id, så kommer nogle af rating rækkerne ikke med (kun det antal, som der er comment-rækker) og omvendt, hvis jeg GROUP BY tab_rating.rating, så kommer der kun det antal comment-rækker med, som der er rating-rækker.

.. men det går jeg ikke ud fra, man kan forhindre? Det var sådan set bare for at slippe for at skulle lave 3 forskellige kald til databasen når tab objektet skal bygges op i PHP..
Avatar billede arne_v Ekspert
10. august 2009 - 04:06 #14
En mulighed var at lade PHP smide duplikater væk.
Avatar billede bmdk Nybegynder
10. august 2009 - 14:06 #15
Det kunne man jo selvfølgelig :) Jeg fandt dig en bedre løsning end den jeg startede ud med, så alt godt! ;)

Tak for hjælpen!
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester