20. september 2005 - 11:46Der er
9 kommentarer og 2 løsninger
brug for hjælp til outer join
jeg har et program der henter tekst osv til menuer fra min mysql db i db er der en tabel der hedder services som indeholder default tekster og så har jeg en ekstra tabel der hedder service_language hvor jeg har tilføjet de ekstra sprog men da det ikke er alle tekster der er oversat så skal den defaulte til teksterne i services tabellen hvis der ikke er en passende entry i service_language tabellen det har jeg prøvet at gøre med left outer join..
hvis default sprog er valgt bruger den denne sql query og får 93 rows
SELECT services.serviceid, services.servicetype, services.servicesubtype, services.displayname, services.serviceurl, services.abouturl, services.dataurl, services.globalid, services.service_modified, services.about_modified, services.data_modified, services.countries, services.countryname, services.provider, services.providername, services.district, services.brickprocessing,services.seq_no, userpackages.packageusage, MAX(userpackages.expiredate) AS expiredate FROM userpackages INNER JOIN packageservices ON packageservices.packageid=userpackages.packageid INNER JOIN services ON services.serviceid=packageservices.serviceid WHERE userpackages.brugerid = 430 AND userpackages.expiredate >= 20050920 AND userpackages.activated= 'yes' GROUP BY services.serviceid, services.servicetype, services.displayname, userpackages.packageusage ORDER BY services.displayname,services.countryname,services.providername, services.seq_no, services.displayname+services.countryname ASC
og hvis et andet sprog er valgt bruger den denne sql query med left outer join og får kun 51 rows tilbage
SELECT services.serviceid, services.servicetype, services.servicesubtype, services.displayname AS defdisplayname ,services.serviceurl, services.abouturl, services.dataurl, services.globalid, services.service_modified, services.about_modified, services.data_modified, services.countries, services.countryname AS defcountryname, services.provider, services.providername, services.district, services.brickprocessing, services.seq_no, userpackages.packageusage, MAX(userpackages.expiredate) AS expiredate, service_language.displayname, service_language.countryname, service_language.lang FROM userpackages INNER JOIN packageservices ON packageservices.packageid=userpackages.packageid INNER JOIN services ON services.serviceid=packageservices.serviceid LEFT OUTER JOIN service_language ON service_language.serviceid = services.serviceid WHERE userpackages.brugerid = '430' AND ( service_language.lang = 'NO' OR service_language.lang IS NULL ) AND userpackages.expiredate >= 20050920 AND userpackages.activated= 'yes' GROUP BY services.serviceid, services.servicetype, services.displayname, userpackages.packageusage ORDER BY service_language.displayname,services.displayname,service_language.countryname,services.countryname,services.providername, services.seq_no, service_language.displayname+service_language.countryname ASC
det er jo mildest talt uhensigtmæssigt at den ikke får 93 rows i begge tilfælde hehe
Den moderne arbejdsplads er i stigende grad afhængig af mødelokaler til at fremme samarbejde, men dette skift medfører også stigende sikkerhedsudfordringer.
Så vidt jeg kan se laver du et outer join til service_language, hvilket skulle gøre at der kommer en post ud selvom der ikke findes én der matcher i service_language
Nu har jeg ikke så meget forstand på mysql, men i MSSQL kan du ikke select et felt i en grouped query hvis feltet ikke er enten med i Group by eller selectes med en aggregete function som Max, Min eller Avg. Alligevel selecter du
service_language.displayname, service_language.countryname og service_language.lang
- uden at de et grouped, det ville give en fejl i MSSQL. For eksperimentets skyld, så prøv at selecte Max() for dem alle:
... MAX(service_language.displayname) AS max_displayname, MAX(service_language.countryname) AS max_countryname, MAX(service_language.lang) AS max_lang ...
Men hvis du droppede at joine med service_language, ville den så komme med alle 93 poster?
Mener du at den kun returnerer 51 poster, eller mener du at der er 42 poster af det 93 hvor felterne er tomme?
Hvis det sidste er tilfældet så kan du bruge IFNULL:
IFNULL(service_language.displayname, services.displayname) AS displayname, IFNULL(service_language.countryname, services.countryname) AS countryname, IFNULL(service_language.lang, 'dansk') AS lang, ...
ja hvis jeg bare bruger den første sql query jeg skrev hvor jeg ikke joiner med service_language så kommer den med 93 og ellers kommer den med 51 og nej det er ikke med 42 tomme rækker det er simpelthen kun de 51 hehe
med IFNULL der fylder den de tomme felter ud men viser stadig kun de 51 rækker
IFNULL(service_language.displayname, services.displayname) AS displayname, IFNULL(service_language.countryname, services.countryname) AS countryname, IFNULL(service_language.lang, 'DA') AS lang FROM userpackages INNER JOIN packageservices ON packageservices.packageid=userpackages.packageid INNER JOIN services ON services.serviceid=packageservices.serviceid
LEFT OUTER JOIN service_language ON service_language.serviceid = services.serviceid AND service_language.lang = 'NB'
WHERE userpackages.brugerid = '430'
AND userpackages.expiredate >= 20050920 AND userpackages.activated= 'yes'
GROUP BY services.serviceid, services.servicetype, services.servicesubtype, displayname ,services.serviceurl, services.abouturl, services.dataurl, services.globalid, services.service_modified, services.about_modified, services.data_modified, services.countries, countryname, services.provider, services.providername, services.district, services.brickprocessing, services.seq_no, userpackages.packageusage, service_language.displayname, service_language.countryname, service_language.lang ORDER BY service_language.displayname,services.displayname,service_language.countryname,services.countryname,services.providername, services.seq_no, service_language.displayname+service_language.countryname ASC
ja det viste sig at rækkefølgen af joins og where betingelser havde en del at sige tak for det nifty IFNULL sjov.. var en del mere elegant end at dobbelt selecte felter hehe smid et svar så får du nogle point som tak for hjælpen !! :))))
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.