Nu har jag problem, som antagligen härstammer i mysql:s begränsade selectreringsfunktioner. Jag gör en bokguide och varje bok kan ha n antal författare. Med en selectlista kan man välja en viss författare (authorId). Med hjälp av detta id ska jag lista alla böcker där vald författaren finns med. (dbms: mysql)
Jag vill ha med följande i listningen:
* Författarens/nas kompletta namn
* Boktitel
* Bokbeskrivning
* Språk
Kan jag få ut rätt information genom att joina alla tabellerna?
select firstName , lastNamem title, description, languageName
from book join bookAuthorList using (bookid)
join bookAuthor using (authorid)
join language on book.languageid = language.languageid
order by title
Om du vill presentera författarna som en kommaseparerad lista så får du göra det i applikationen.
Hmm, jag får inte riktigt till det. De värdena inom parantes, hänvisar de till någon tabell eller en variabel?
$sql ="select ba.authorFirstName, ba.authorLastName, b.title, b.comments, l.language
from book b join bookAuthorList bal using (bookId)
join bookAuthor ba using (authorId)
join language l on b.languageId = l.languageId
order by b.title";
You have an error in your SQL syntax near 'using (bookId) join bookAuthor ba using (authorId) join language l on' at line 2
Det som står efter using skall vara ett kolumnnamn
select * from a join b using(c)
är (nästan*) samma som
select * from a join b on a.c = b.c
Jag hade för mig att Mysql stödde join using ...
$sql ="select ba.authorFirstName, ba.authorLastName, b.title, b.comments, l.language
from book b inner join bookAuthorList bal
on b.bookId = bal.bookid
inner join bookAuthor ba
on bal.authorId = ba.authorid
inner join language l
on b.languageId = l.languageId
order by b.title";
Så länge man inte ställer ett krav på att en viss författare ska finnas med så fungerar detta utmärkt. Men om jag tex ställer ett krav att:
Lista alla böcker där authorId 8 finns med.
Då hittar den iofs rätt bok och rätt författare, men bara en av flera möjliga författare om boken har flera författare. Jag kan tänka mig att man får välja ut övriga författare till boken med en egen sql-fråga i loopen. Men det är kanske någon som har ett bättre förslag?
$sql ="select ba.authorFirstName, ba.authorLastName, b.title,
b.comments, l.language
from book b inner join bookAuthorList bal
on b.bookId = bal.bookid
inner join bookAuthor ba
on bal.authorId = ba.authorid
inner join language l
on b.languageId = l.languageId
where bal.authorId = 8
order by b.title";
Enligt denna sida ska mysql faktiskt göra det. Men det verkar som att man måste ange vilken typ av join (inner, left, right osv) man vill använda. http://www.mysql.com/doc/en/JOIN.html
$sql ="select ba.authorFirstName, ba.authorLastName, b.title, b.comments, l.language
from books b inner join bookAuthorList bal using (bookId)
inner join bookAuthor ba using (authorId)
inner join language l on b.languageId = l.languageId
order by b.title";
Fungerar, dock med samma problem med att man inte får ut alla författare vid ett specificerat villkor på författare.
En tanke slår mig - pröva utan order by. Får du samma fel?
I så fall: Jag antar att följande inte gör någon skillnad? (Borde det inte göra.)
$sql ="select ba.authorFirstName, ba.authorLastName, b.title, b.comments, l.language
from books b, bookAuthorList bal, bookAuthor ba, language l
where b.bookId = bal.bookId and ba.authorId = bal.authorId
and b.languageId = l.languageId and ba.authorId = 8
order by b.title";
För att få fram det du vill så behövs en subselect
$sql ="select ba.authorFirstName, ba.authorLastName, b.title, b.comments, l.language
from book b inner join bookAuthorList bal
on b.bookId = bal.bookid
inner join bookAuthor ba
on bal.authorId = ba.authorid
inner join language l
on b.languageId = l.languageId
where bal.bookid in (
sekect bookid from bookAuthorList
where authorId = 8)
order by b.title";
Utan subselect så får man använda flera frågor och temporärtabeller.
Enligt denna sida ska mysql faktiskt göra det. Men det verkar som att man måste ange vilken typ av join (inner, left, right osv) man vill använda.
Det är ju helt onödigt enligt standard att behöva ange inner i samband med join.
Tack LarsG! Det var det jag misstänkte. Eftersom jag sitter med mysql 3.xx så får jag använda flera frågor eller nöja mig med att visa en författare (vald författare) i sökningen.
När är det bättre att använda using join istället för en "vanlig" join?
Som jag nämnde så är using i stort sett bara en förkortning av en join med ett on-villkor. Det kan vara bekvämt vid inner join men i stort tycker jag att det är en ganska meningslös konstruktion.
[geek-info]
Det finns en liten distinktion (som Mysql har missat, (rätta mig om jag har fel)), jämfört med att använda on.
Om man skriver
select * from a join b on a.id = b.id
så blir det två kolumner som heter id i resultatet och man kan använda
select a.id as aid, b.id as bid from a join b on a.id = b.id
men däremot om man skriver
select a.id as aid, b.id as bid from a join b using(id)
så skall man få fel enligt standard eftersom resultatet i detta fall bara innehåller en förekomst av kolumnen id och tillhör inte någon tabell så det går inte att kvalificera namnet.
Om man använder inner join så är väl detta helt ok då a.id och b.id har samma värde och det finns ingen anledning att ha med båda. Däremot om man har en outer join
select * from a left join b using(id)
så blir det konstigt eftersom b.id i vissa fall kan vara null och då finns det inget sätt att referera b.id.
För att testa om Mysql gör fel så kan man utföra följande
create table t1(c1 int);
create table t2(c1 int);
insert into t1 values(2);
insert into t2 values(2);
select * from t1 inner join t2 using(c1);
[/geek-info]
...[geek-info]
Det finns en liten distinktion (som Mysql har missat, (rätta mig om jag har fel)), jämfört med att använda on.
... men däremot om man skriver
select a.id as aid, b.id as bid from a join b using(id)
så skall man få fel enligt standard eftersom resultatet i detta fall bara innehåller en förekomst av kolumnen id och tillhör inte någon tabell så det går inte att kvalificera namnet.
[/geek-info]
Natural join är ju också en tveksam och försåtlig konstruktion.
select id from a natural join b
är samma som
select id from a join b using(<lista med alla kolumner vars namn finns i båda tebellerna>)
T.ex. om det inte finns några gemensamma kolumner så kommer det att fungera som en kryss-produkt.
Ett annat problem är att om man lägger till en kolumn till en tabell så kan det påverka frågan så att man får ett annat resultat. Natural join skulle jag inte rekommendera att använda.
Natural join är ju också en tveksam och försåtlig konstruktion....
select id from a join b using(<lista med alla kolumner vars namn finns i båda tebellerna>)
T.ex. om det inte finns några gemensamma kolumner så kommer det att fungera som en kryss-produkt...
Det är nog så riktigt. Men man vet väl för höge farao hur den egna databasen ser ut? Om den är vettigt modellerad och befinner sig i minst 3NF, är det då någon risk?
Visst, om man har en färdig datamodell så är det nog inget problem, men om jobbar lite ad-hoc så och t.ex. har kolumner med namnet description som man nog inte vill joina.
Natural join tllför ju ingen funktionalitet heller.
253 ms totalt · 4 externa anrop · v20260731065814-full.d34c6d5a