Vinnaren i pepparkakshustävlingen!
  • 1
  • 2
2011-06-05, 20:58
  #1
Medlem
Luciditys avatar
Tabellen Personer har attributen Namn och ID
Tabellen Favoritdjur har attributen Person_ID och Djur_namn

En person kan alltså ha flera favoritdjur.

Jag skulle vilja skriva ut det på det här sättet: http://i.imgur.com/XjTmN.jpg

Går det att göra i ett SQL kommando? Det enda jag kan tänka mig nu är att först välja Namn och ID från Person, skriva ut det i en loop och vid varje varv i loopen gör en ny förfrågan som hämtar favoritdjuren för den personen. Men det skulle bli 50 olika förfrågningar om jag har 50 personer i databasen. Jag förstår att man gör det med Joins på nåt sätt därav titeln på tråden.
Citera
2011-06-05, 21:45
  #2
Medlem
blackadder1s avatar
Nåt sån här kanske?
Kod:
SELECT p.idPerson, d.djurnamn FROM person p
JOIN Favoritdjur d ON p.idPerson = d.Person_ID
Citera
2011-06-05, 21:47
  #3
Medlem
Luciditys avatar
Citat:
Ursprungligen postat av blackadder1
Nåt sån här kanske?
Kod:
SELECT p.idPerson, d.djurnamn FROM person p
JOIN Favoritdjur d ON p.idPerson = d.Person_ID
Då kommer raderna se ut såhär: (tror jag, inte testat)
...
Bob, Hund
Bob, Fisk
Bob, Elefant
...
Hur ska jag då skriva ut dem till en tabell såsom i mitt screenshot?
Citera
2011-06-05, 21:52
  #4
Medlem
blackadder1s avatar
Jag tror att det är det närmaste du kan komma.
Resten får du sköta i ditt program/websida.
Edit: Om du kör mysql så kan du kolla upp funktionen GROUP_CONCAT.
__________________
Senast redigerad av blackadder1 2011-06-05 kl. 21:58.
Citera
2011-06-05, 21:59
  #5
Medlem
Luciditys avatar
Det stämmer nog, detta är snarare ett php problem. Och jag fått en ide om hur jag kan lösa det där (med samma kommando som du föreslog).
Edit: GROUP_CONCAT ser bra ut, ska ta och försöka med det först.
Edit2: Exemplet jag använde är bara en förenklad version av mitt egentliga problem som kommer bli otroligt avancerat om ens möjligt med GROUP_CONCAT så jag gör en halvfin lösning i php istället.
__________________
Senast redigerad av Lucidity 2011-06-05 kl. 22:04.
Citera
2011-06-05, 22:06
  #6
Medlem
blackadder1s avatar
Otestat så skulle det bli nåt liknande.
Kod:
SELECT p.idPerson, GROUP_CONCAT(d.djurnamn SEPARATOR ',') FROM person p
JOIN Favoritdjur d ON p.idPerson = d.Person_ID
GROUP_BY p.idPerson;
Citera
2011-06-05, 22:12
  #7
Medlem
Luciditys avatar
Citat:
Ursprungligen postat av blackadder1
Otestat så skulle det bli nåt liknande.
Kod:
SELECT p.idPerson, GROUP_CONCAT(d.djurnamn SEPARATOR ',') FROM person p
JOIN Favoritdjur d ON p.idPerson = d.Person_ID
GROUP_BY p.idPerson;
I mitt verkliga problem ska det finnas html med länkar som innehåller id och så har djuren ibland efternamn. Så GROUP_CONCAT passar som sagt inte

Edit: Det jag gör är ett crafting-system till mitt spel. För att göra en Iron-bar kan man behöva 2 Iron-ore. En sak kan behöva flera material. Ett problem jag stötte på nu är att jag måste selecta Items.name 2 gånger, en gång för itemet man vill göra, och en gång för materialet som behövs... Hur ska de gå till?

Om vi ska hålla oss till enklare exempel: Ett djur kan ha flera FavoritDjur, och allting går utifrån IDs så man måste selecta Djur.namn 2 gånger samt göra 2 stycken join, en för djurets namn och en för ett av hans favoritdjur. Detta är det krångligaste SQL-problemet jag någonsin stött på. En 1-många relation inom samma tabell där allt är ID som är kopplat till ett namn.

Edit2: Efter lite googlande stötte på jag "Double join" vilket fick mig att komma fram till den här förfrågningen
Kod:
SELECT Item1.idItem1.nameItem1.hasMaterialMat1.idMat1.name,
        
Item2.idItem2.nameItem2.hasMaterialMat2.idMat2.nameCraftingMats.nums
        FROM Crafting
        INNER JOIN Items 
AS Item1 ON Crafting.item_id=Item1.id
        INNER JOIN Material 
AS Mat1 ON Crafting.mat_id=Mat1.id
        INNER JOIN CraftingMats ON Crafting
.id=CraftingMats.craft_id
        INNER JOIN Items 
AS Item2 ON CraftingMats.item_id=Item2.id
        INNER JOIN Material 
AS Mat2 ON CraftingMats.item_mat=Mat2.id 
Lägg märke till hur jag gör "INNER JOIN Items" två gånger med AS Item1 och AS Item2 och sedan selectar därifrån.
Nu ska jag bara klura ut ett sätt att skriva ut allt som på bilden i första inlägget.
__________________
Senast redigerad av Lucidity 2011-06-05 kl. 22:57.
Citera
2011-06-05, 23:14
  #8
Medlem
Luciditys avatar
Det funkar Kan inte redigera förra inlägget då det gått mer än 60 minuter. Här är all kod:
Kod:
echo '<table><tr><th>Item</th>
    <th>Reagents</th>
    <th>Craft</th></tr>'
;
$stmt $mysqli->prepare("SELECT Item1.id, Item1.name, Item1.hasMaterial, Mat1.id, Mat1.name,
        Item2.id, Item2.name, Item2.hasMaterial, Mat2.id, Mat2.name, CraftingMats.nums, Crafting.id
        FROM Crafting
        INNER JOIN Items AS Item1 ON Crafting.item_id=Item1.id
        INNER JOIN Material AS Mat1 ON Crafting.mat_id=Mat1.id
        INNER JOIN CraftingMats ON Crafting.id=CraftingMats.craft_id
        INNER JOIN Items AS Item2 ON CraftingMats.item_id=Item2.id
        INNER JOIN Material AS Mat2 ON CraftingMats.item_mat=Mat2.id"
);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($craft_id$craft_name$craft_hasMat$craft_matId$craft_Matname,
        
$rea_id$rea_name$rea_hasMat$rea_matId$rea_matName$nums$id);
$lastCraftName "";
$lastCraftId 0;
while(
$stmt->fetch()){
    
$craftItem = new ItemLink($craft_id$craft_name$craft_hasMat0$craft_matId$craft_Matname0"");
    
$reaItem = new ItemLink($rea_id$rea_name$rea_hasMat0$rea_matId$rea_matName0"");
    if(
$lastCraftName==""){
        
//första loopen
        
echo '<tr>';
        echo 
"<td>{$craftItem->getLink()}</td>";
        echo 
'<td>'.$reaItem->getLink().($nums!=" x$nums"");
    }
    else if(
$lastCraftName==$craftItem->getName()){
        
//fler reagents
        
echo '<br />'.$reaItem->getLink().($nums!=" x$nums"");
    }
    else{
        
//nytt item
        
echo '</td>';
        echo 
'<td><a href="craft.php?id='.$lastCraftId.'"><button>Craft</button></a></td></tr>';
        echo 
'<tr>';
        echo 
"<td>{$craftItem->getLink()}</td>";
        echo 
'<td>'.$reaItem->getLink().($nums!=" x$nums"");
    }
    
$lastCraftName $craftItem->getName();
    
$lastCraftId $id;
}
//lägg till Craft-knapp på sista itemet
echo '</td>';
echo 
'<td><a href="craft.php?id='.$lastCraftId.'"><button>Craft</button></a></td></tr>';
$stmt->close();
echo 
'</table>'
Och såhär ser det ut http://i.imgur.com/gyJ85.jpg

Säg till om ni undrar något. Som ni sär bygger jag på tabellen på olika sett beroende på om det är ett nytt item eller bara mer reagents som behövs för förra itemet.

Nu ska jag bara fixa server-sidan som kollar ifall användaren har alla material som behövs, och isåfall tar bort den från inventory och lägger till itemet man har craftat
__________________
Senast redigerad av Lucidity 2011-06-05 kl. 23:38.
Citera
2011-06-06, 00:49
  #9
Medlem
z0mfg(ish)s avatar
Djur borde ha en egen tabell, sen är tabellen favoritdjur enbart bestående av personens id samt djurets id.
Självklart kan en person förekomma fler än 1 gång, likväl ett djur.
Citera
2011-07-26, 13:59
  #10
Medlem
hmm, jag har bygget en sql fråga som jag tror funkar på samma sätt som en join?
Men det kanske den inte gör. Vad är skillnaden?
Kod:
SELECT a.year as yeara.storea.createdb.username as username
        FROM db a
user b
        WHERE a
.uid=b.uid 
        ORDER BY a
.created DESC 
Citera
2011-07-26, 14:35
  #11
Moderator
Protons avatar
Citat:
Ursprungligen postat av estone
hmm, jag har bygget en sql fråga som jag tror funkar på samma sätt som en join?
Men det kanske den inte gör. Vad är skillnaden?
Kod:
SELECT a.year as yeara.storea.createdb.username as username
        FROM db a
user b
        WHERE a
.uid=b.uid 
        ORDER BY a
.created DESC 
Skillnaden ligger i läsbarheten och möjligen hur query analyzern bygger upp planen för att exekvera frågan. Personligen tycker jag man inte ska blöta ner WHERE-villkoren med en join utan låta where endast styra urvalet, men resultatet av frågan kommer bli som en INNER JOIN mellan user och db.

Lite off topic:
Problemen uppstår om man vill JOINA på annat sätt, dvs en LEFT eller RIGHT join, då funkar det inte att göra sådär eftersom frågan endast kommer returnera rader där id förekommer i bägge tabellerna.
Citera
2011-07-26, 18:39
  #12
Medlem
Citat:
Ursprungligen postat av Proton
Skillnaden ligger i läsbarheten och möjligen hur query analyzern bygger upp planen för att exekvera frågan. Pe...
ok. Intressant info. thx
Det är nog smartare att lära sig join även om jag gilla min variant.
Citera
  • 1
  • 2

Stöd Flashback

Flashback finansieras genom donationer från våra medlemmar och besökare. Det är med hjälp av dig vi kan fortsätta erbjuda en fri samhällsdebatt. Tack för ditt stöd!

Stöd Flashback