FAQ |
Kalender |
![]() |
#1 | ||
|
|||
Medlem
|
Hejsan,
Jag har tänkt göra en "Kunder som har köpt denna produkt har även köpt..." funktion. Nu är frågan har jag gör en "bra" mysql fråga för att plocka ut 5 stycken slumpmässigt och olika produkter som kunderna också har köpt baserat på den aktuella produkten som visas. Jag lagrar ordrar på följande sätt: orderInfo => en tabell med orderinformation, t.ex. namn, adress, etc. orderItem => en tabell med beställda produkter med orderID som pekar på orderInfo och itemID som pekar på produkten. Så här ser min fråga ut just nu: mysql_query("SELECT DISTINCT t2.itemID as itemID FROM orderItem as t1, orderItem as t2 WHERE t1.itemID = \"$itemID\" AND t1.orderID = t2.orderID ORDER BY rand() LIMIT 5"); Men med explain ger frågan detta: table type possible_keys key key_len ref rows Extra t1 ALL NULL NULL NULL NULL X Using where; Using temporary; Using filesort t2 ALL NULL NULL NULL NULL X Using where Vilket inte ser så bra ut (X = antalet sålda produkter)? Sen utifrån detta skulle jag även behöva plocka ut produktinfo från en annan tabell baserat på itemID och vill helst slippa göra detta i en loop (som jag tidigare brukar göra ![]() Någon som har en ide om hur man kan göra detta på ett effectivt sätt? |
||
![]() |
![]() |
![]() |
#2 | ||
|
|||
Medlem
|
Ingen som har någon idé eller något tips om hur detta kan göras på ett bra sätt? Eller är mitt sätt tillräckligt effektivt?
|
||
![]() |
![]() |
![]() |
#3 | ||
|
|||
Medlem
|
Kod:
mysql_query("SELECT DISTINCT t2.itemID as itemID FROM orderItem as t1, orderItem as t2 WHERE t1.itemID = \"$itemID\" AND t1.orderID = t2.orderID ORDER BY rand() LIMIT 5"); Någon som har en ide om hur man kan göra detta på ett effectivt sätt?[/QUOTE] vet inte om det blirmkteffektivare, men det kanske går att dela upp queryn i två-tre. Såna där t1.orderID = t2.orderID brukar bli hemskt ineffektiva. kanske såhär Kod:
SELECT orderID FROM orderItem WHERE itemID="$itemID" ORDER BY rand() LIMIT 10; /* kanske 100? :) */ SELECT itemID FROM orderItem WHERE $idlist Jag tror det borde bli effektivare, men hinner inte räkna nu. |
||
![]() |
![]() |
![]() |
#4 | ||
|
|||
Medlem
|
Jo jag hänger nog med på vad du menar.
Det kan dock bli ett problem då en del ordrar bara har en produkt beställda. Om man har "otur" så är det dessa som plockas ut i den första queryn och då fungerar det inte. Nu ser queryn som jag använder för tillfället ut så här: SELECT count(t2.itemID) as num, t2.itemID as id, t3.name as name, t3.price as price, t3.offer as offer FROM orderItem as t1, orderItem as t2 LEFT JOIN boardgame as t3 ON t3.id = t2.itemID WHERE t1.itemType = 1 AND t2.itemType = 1 AND t1.itemID = \"$itemID\" AND t1.orderID = t2.orderID AND t1.itemID != t2.itemID GROUP BY t2.itemID ORDER BY num DESC, RAND() LIMIT 5; Med denna query så får jag ut de vanligast "också beställda" produkterna och slumpar deras ordning om fler är lika vanliga. Men som sagt tror jag inte denna method är "bra" och skulle gärna vilja ha hjälp att förbättra det om det är möjligt? Skulle även gärna ha samma resultat, alltså att man listar de vanligaste "också beställda" produkterna. Det kanske är så att min metod inte är så farlig? Jag har ingen vidare koll på hur "jobbiga" min query är för databasen och servern? Säg att det kanske är totalt 2000 rader i orderItem. Detta skulle enligt min beräkning ge typ 4000000 rader att gå igenom? låter på tok för mycket för att vara ok? |
||
![]() |
![]() |
![]() |
#5 | ||
|
|||
Medlem
|
kolla hur lång tid queryn tar, explain är ju bra också men exekveringstiden säger en del...
om jag var du skulle jag nog cacha "vanligast beställda", borde inte ta så förfärligt mktplats och snabbar uppen hel del. Men det är ju som vanligt den där konfliketn tid/plats |
||
![]() |
![]() |
![]() |
#6 | ||
|
|||
Medlem
|
Queryn tar via phpMyAdmin 0.0135 sek just nu. Kollat man på sidan där jag använder funktionen så laddas sidan direkt så där är det inte heller några problem.
Men frågan är hur det bli i framtiden när man säljer fler och fler produkter? Tanken att spara ner "också beställda" produkter låter inte så dumt. Man skulle t.ex. kunna göra en tabell: soldItemID | alsoSoldItemID | numAlsoSoldItem Då blir queryn (taget från huvudet så det kanske inte stämmer?) lite enklare och förhoppningsviss mer effektiv: SELECT t2.id, t2.name, t2.price FROM alsoSold as t1 LEFT JOIN boardgame as t2 ON t2.id = t1.alsoSoldItemID WHERE t1.soldItemID = \"$itemID\" ORDER BY t1.numAlsoSoldItem DESC LIMIT 5; Nackdelen här är dock som du säger utrymmet. Men då vi bara har ca 400 produkter i systemet så blir det max: 160000 rader vilket inte tar så himla stor plats. Detta gör även att det så länge vi bara har 400 produkter blir det aldrig "jobbigare" för databasen oavsätt hur mycket vi säljer. Får titta lite mer på det när vi har sålt lite fler produkter ![]() |
||
![]() |
![]() |
![]() |
#7 | ||
|
|||
Mycket flitig postare
|
Citat:
Och idéen med en hjälptabell (alsoSold) är ävl en bra optimering. Glöm dock inte att en av de viktigaste reglerna vid optimering är att man inte skall optimera det som inte behöver optimeras. Spontant låter ju "0.0135 sek" som om du inte behöver optimera just nu. När databasen växt så kontrollerar du igen och den (hamska) dagen då du tycker den börjar gå för långsamt, då optimerar du. Förslagsvis med "alsoSold" som kan fyllas en gång per dygn eller liknande. |
||
![]() |
![]() |
Svara |
|
|