Jag har en blogg... nu vill jag tagga mina blogginlägg så man snabbt hittar likartade inlägg. Att söka reda på en tagg går enkelt, men hur löser man det om man vill att två eller fler måste stämma överens för att blogginlägget skall visas? Vad är det i dina tabeller? Detta är bara namn tagna ur luften... Ok, "bloggmatchar" var väl lite skumt. Jag skulle kallat det bloggar, taggar och bloggtaggar. Det där såg intressant ut... :) Då så... "bygga bort IN-satserna"? Jepp jag vet, men det är det som jag är ute efter är just enbart att få med de specifika som man valt... Förutom att den artikeln pratar om IN(SELECT ...). Så sant så sant... Jag har ju min SQL-sats som jag pillat ihop och gör jag om den till JOIN så är det snabbt att kolla via phpMyAdmin ev. tidsvinsten... Nu har jag provat att leka lite med denna... <b>>BloggID i "SELECT BloggID FROM (SEL... " är det i tabellen "BloggTaggar" eller är du "nere" i det du kallar "Bloggar"?</b>Tagga blogginlägg...
Fick tips om denna SQL-sats, där man har bloggen, matchningar och tagg-ord i tre separata tabeller och sen stoppar in orden i en IN-sats.
Select bloggar.bloggid from
bloggar,
bloggmatchar,
bloggtaggar
where
bloggar.bloggid = bloggmatchar.bloggid and
blogmatchar.taggid = bloggtaggar.taggid and
bloggtaggar.namn in ('öl', 'chips')
Dock så tar denna med alla inlägg som har "öl" eller "chips" som tagg ord... inte "öl" och "chips".
Hur löser man sådant här? Har ni några idéer eller kan tipsa om någon artikel eller sökord på nätet som man kan läsa mera på?Sv: Tagga blogginlägg...
De har inte så talande namn...
Det enklaste (om du inte ska göra mer avancerad sökning) är mängdoperationer.Sv:Tagga blogginlägg...
Tabell "bloggar" skulle då vara "id" och "blogg text", tabell "bloggmatchar" är en koppling mellan "blogg id" och "tagg id". Så att man kan återanvända alla tagg namnen och till slut så har vi tabellen "bloggtaggar" som innhåller ett "ID" och ett "tagg ord".Sv: Tagga blogginlägg...
Hur som helst, det "enklaste" är att bygga upp ett stort uttryck (jag kör med mina namn för att göra det enklare att skriva):
1. Hämta ut ett taggID
SELECT TaggID FROM Taggar WHERE TaggOrd = "Öl"
2. Hämta ut alla blogginlägg som har den taggen
SELECT BloggID FROM Bloggtaggar WHERE TaggID = (SELECT TaggID FROM Taggar WHERE TaggOrd = "Öl")
3. Gör samma sak, fast för den andra taggen
SELECT BloggID FROM Bloggtaggar WHERE TaggID = (SELECT TaggID FROM Taggar WHERE TaggOrd = "Chips")
4. Ta bara de BloggID:na som finns i båda
(SELECT BloggID FROM Bloggtaggar WHERE TaggID = (SELECT TaggID FROM Taggar WHERE TaggOrd = "Öl"))
INTERSECT
(SELECT BloggID FROM Bloggtaggar WHERE TaggID = (SELECT TaggID FROM Taggar WHERE TaggOrd = "Chips"))
5. Använd detta för att få fram all blogginlägg
SELECT BloggID, BloggText FROM Bloggar WHERE BloggID IN
((SELECT BloggID FROM Bloggtaggar WHERE TaggID = (SELECT TaggID FROM Taggar WHERE TaggOrd = "Öl"))
INTERSECT
(SELECT BloggID FROM Bloggtaggar WHERE TaggID = (SELECT TaggID FROM Taggar WHERE TaggOrd = "Chips")))
Ytterligare en variant är att hämta ut alla och räkna antalet:
SELECT BloggID FROM (SELECT BloggID FROM BloggTaggar NATURAL JOIN Taggar WHERE TaggID IN ("Öl", "Chips")) GROUP BY BloggID HAVING COUNT(BloggID) = 2
2:an måste anpassas till antalet ord. Om man vill ha något i stil med ("A" OCH "B") ELLER "C" så är den första varianten att föredra (och det kanske är omöjligt att lösa det med den andra).Sv:Tagga blogginlägg...
Namnen är som sagt var inte jag som pillade ihop, utan fick den ifrån en annan... jag byggde en testvariant med INSTR som fungerade klockrent, men istället fick man en TABLE-scan på databasen som kanske inte är att föredra... Då låg alla bloggtaggar i samma fält...
Då fick jag detta uppbyggnadstips med namnen. Efter lite tester så insåg att det inte fungerade som jag ville och av lat het så skrev jag inte om dessa vid mitt prov och postade detta här i forumet...
Hur blir bealstningen på MySQL-server om man kör detta eller om man skulle lägga alla ord i ett fält och köra "MATCH" på dessa istället?Sv: Tagga blogginlägg...
Löste det med hjälp av denna, med lite modifikation... ska prova att skriva om den och bygga bort IN-satserna vid senare tillfälle så därför så visar jag inte den färdiga SQL-satsen.
SELECT BloggID FROM (SELECT BloggID FROM BloggTaggar NATURAL JOIN Taggar WHERE TaggID IN ("Öl", "Chips")) GROUP BY BloggID HAVING COUNT(BloggID) = 2
Den är lätt att utöka med flera ord CB därav anledningen till att jag gick vidare med denna...
Tack Niklas...Sv:Tagga blogginlägg...
<b>>Den är lätt att utöka med flera ord CB därav anledningen till att jag gick vidare med denna...</b>
Notera bara att du enbart kommer kunna få "exakt alla de här orden måste vara med". Ska du ha mer generella villkor får du ta det första alternativet.Sv: Tagga blogginlägg...
Bygga bort IN menar jag med att ersätta dessa med JOIN eftersom IN är prestandakrävande, i alla fall enl. denna artikel http://www.aspsidan.se/default.asp?page=readArticle&artId=615Sv:Tagga blogginlägg...
Här är det tvärtom, här måste du lägga in dem i en temporär tabell först. I vissa fall är det snyggare och möjligtvis snabbare, men knappast här.
Sen ska man tänka på två grejer:
1. Preoptimization is the root of all evil.
2. Det är helt och hållet beroende på databasmotor, index osv. Ändra inte utan att göra en kontroll på att det faktiskt går fortare...Sv: Tagga blogginlägg...
Tack igen Niklas!Sv:Tagga blogginlägg...
SELECT BloggID FROM (SELECT BloggID FROM BloggTaggar NATURAL JOIN Taggar WHERE TaggID IN ("Öl", "Chips")) GROUP BY BloggID HAVING COUNT(BloggID) = 2
BloggID i "SELECT BloggID FROM (SEL... " är det i tabellen "BloggTaggar" eller är du "nere" i det du kallar "Bloggar"? För som jag får till det så är jag kvar i " taggar och bloggtaggar" och för att plocka t.ex. title så måse jag JOINA denna med ytterligare en tabell "Bloggar". Det lättaste sättet hade varit att köra med IN men då är man där enl. artiklen om prestanda skillnader.
Nu är jag här i min SQL-sats...
-------------------------------------------------------------------------------------------------------------
SELECT `id`, `title`, `text`, `date` FROM bloggar LEFT JOIN (SELECT BloggID FROM BloggTaggar NATURAL JOIN Taggar WHERE TaggName IN ('Öl','Chips')) as newMatchtable ON BloggID = id GROUP BY BloggID HAVING COUNT(BloggID) = 2Sv: Tagga blogginlägg...
Eftersom jag inte anropar "Bloggar" öht så är det från BloggTaggar
<b>>För som jag får till det så är jag kvar i " taggar och bloggtaggar" och för att plocka t.ex. title så måse jag JOINA denna med ytterligare en tabell "Bloggar". Det lättaste sättet hade varit att köra med IN men då är man där enl. artiklen om prestanda skillnader. </b>
Ja, där är det en join som är aktuell, men skriv det som;
SELECT `id`, `title`, `text`, `date` FROM bloggar LEFT JOIN (SELECT BloggID FROM BloggTaggar NATURAL JOIN Taggar WHERE TaggName IN ('Öl','Chips') GROUP BY BloggID HAVING COUNT(BloggID) = 2) as newMatchtable ON BloggID = id
så kör du group by före yttre joinen