Hur hämtar jag ut alla kategorier för den? Problemet är ju att alla underkategorier inte har id 1 som parent, utan nivå tre har nivå två som parent. Det räcker om den sträcker sig till nivå tre om det är lättare, men min struktur är tänkt att funka för obegränsat med nivåer så om det finns en lösning som hämtar rätt oavsett om det inte finns några undernivåer eller om det finns massvis så är det ett stort plus. Viktigt är dock att det går att hämta grenen både från roten (huvudkategori) eller från en "kvist" (subkategori).
Förslag?
SELECT * FROM kategorier
WHERE parent = $id OR [i]parentsparent[/i] = $id
parentsparent är inget som finns, men jag försöker beskriva det jag vill åt :)
Jag kollade på MySQL och CTE (eller Derived table WITH clause, som det officiella namnet är) och tydligen lades det in en Feature Request för detta i januari 2006. Men vad jag kan se har den inte ens blivit prioriterad ännu. Så där verkar det vara kört. :-(
Återstår alltså att hårdkoda antalet nivåer. Hur tänkte du dig att få resultatet presenterat? Bara de råa posterna från den grenen?
Jag har löst det hehe, men det blev nog rätt grisigt ;)
Lösningen jag gjorde var att göra en if-check som kollar om 1) det är en huvudkategori, 2) det är en subkategori eller 3) det är en vanlig kategori.
I fall 1-2) så loopade jag ut en hel radda med "parent = X OR parent = X OR ..." och i fall 3) så hämtade jag helt enkelt där parent = X utan några OR.
Det funkar och verkar inte vara jätteslött så det duger åt mig! Tack för hjälpen!
Tack! Det ser ju onekligen rätt ut, men kruxet är att jag ska få in det i en JOIN med en annan tabell också :)
SELECT * FROM poster
LEFT JOIN kategorier k
ON poster.kategori = k.id
WHERE poster.kategori = $id
OR k.parent = $id
OR EXISTS(SELECT * FROM kategorier WHERE kategorier.parent = $id AND kategorier.id = k.parent)
Typ så?
Det kanske bör vara nån annan JOIN men. Jag joinar ju med k.id. Hur går det ihop med din kod?
Orkar du? Tack! :)
Edit/ I sammanhanget kan nämnas att poster.kategori aldrig innehåller id till en huvud/subkategori.
Hmm, låt mig se om jag har förstått din datamodell rätt:
Din tabell "poster" innehåller ett antal poster där några (men inte alla) hör till en viss kategori. Denna kategori finns i tabellen "kategori" och har aldrig några underkategorier, dvs är alltid ett löv i hierarkin. Rätt gissat så långt?
Sedan är det lite otydligt vad du vill ha ut. Vad jag förstår vill du kunna ange id:t på en godtycklig kategori-nod i hierarkin och få ut alla poster som hör till denna eller någon underliggande kategori. Datat du vill ha av varje är samtliga fält från "poster" och motsvarande fält från "kategori". Stämmer det?
Nästan rätt. Varje post har alltid en kategori, ett löv. Det är egentligen posterna jag vill ha ut, från önskade kategorier.
Man ska kunna söka bland posterna och genom en select-box välja om man vill hämta ut samtliga poster i en 1) huvudkategori (ibland parent och ibland parents parent), en 2) subkategori (parent) eller direkt från ett 3) löv.
Jag har som sagt löst det, men det blev en if-lösning med tre val för varje 1-3) där 1) först loopade ut sina barn (subkategorier) som därefter loopade ut sina (löv). 2) fick bara en loop som listade alla löv och 3) hämtade direkt där parent = id.
Detta känns som en väldig omväg och jag fick som sagt fler och fler OR i min sql-fråga för alt. 1-2)
Det rullar som sagt på obehindrat, men jag tar gärna emot ett snyggare förslag! :)
Edit/ Kategorierna kommer i framtiden att vara hyfsat fasta och jag har ett till kategorifält som jag inte nämnt (fullösning), is_parent. Detta fält har 1 på alla kategorier som är huvudkategori eller subkategori och 0 på alla löv. Därav var det enkelt att göra min if-sats ovan. Jag kollade helt enkelt om "parent == 0 && is_parent == 1" då har vi en huvudkategori. Om "parent != 0 && is_parent == 1" så har vi en subkategori och om "parent != 0 && is_parent == 0" då har vi ett löv. Fullösning jag vet, men is_parent hjälpte mig oerhört då jag enkelt ville kunna kolla vilken typ av kategori det rörde sig om, speciellt i min select-box där jag ville skriva ut olika klassnamn för att formatera olika kategorier.
Nästan rätt. Varje post har alltid en kategori, ett löv.
Okej. Det var ett antagande baserat på att du visade LEFT JOIN mellan poster och kategorier.
Det är egentligen posterna jag vill ha ut, från önskade kategorier.
Man ska kunna söka bland posterna och genom en select-box välja om man vill hämta ut samtliga poster i en 1) huvudkategori (ibland parent och ibland parents parent), en 2) subkategori (parent) eller direkt från ett 3) löv.
Prova då:
SELECT *
FROM poster
WHERE kategori IN (
SELECT *
FROM kategorier k
WHERE id = $id
OR parent = $id
OR EXISTS(SELECT * FROM kategorier WHERE parent = $id AND id = k.parent)
)
där $id alltså innehåller id:t på den kategori-nod och neråt som du vill ha ut samtliga poster från.
Jag har lite annat lull-lull iofs, men jag tycker mig ha överfört din sql rätt. Jag får: "Operand should contain 1 column(s)" när jag lägger till din snutt. Vad kan det vara?
SELECT posts.*, posts_rel.*, persons.person, users.username, (SELECT COUNT(*)
FROM posts_rel
WHERE p_r_parent = p_id
) has_translation
FROM posts
LEFT JOIN posts_rel
ON p_id = p_r_parent
LEFT JOIN users
ON p_creator = u_id
LEFT JOIN persons
ON p_person = p_id
WHERE NOT (p_visibility = 0)
AND p_kategori IN (
SELECT * FROM kategorier k
WHERE k_id = 2
OR k_parent = 2
OR EXISTS(
SELECT * FROM kategorier
WHERE k_parent = 2
AND k_id = k.k_parent
)
)
(Samtliga mina JOINS kanske bör vara INNER eller bara JOIN eftersom det alltid finns nåt i båda tabellerna? Jag kan inte de olika joinsen än) :D
Skippar jag allt från: AND p_kategori IN... så funkar frågan. Annars ber den om 1 column.
(Samtliga mina JOINS kanske bör vara INNER eller bara JOIN eftersom det alltid finns nåt i båda tabellerna? Jag kan inte de olika joinsen än) :D
Byt till INNER JOIN om du vet att du alltid har matchande poster. Ju mer du talar om för en relationsdatabas, desto bättre sökstrategi kan den komma fram till.
Skippar jag allt från: AND p_kategori IN... så funkar frågan. Annars ber den om 1 column.
Himla hjälpsamt av den att inte berätta vilken kolumn den saknar... :(
Om du bara kör:
SELECT posts.*
FROM posts
WHERE NOT (p_visibility = 0)
AND p_kategori IN (
SELECT * FROM kategorier k
WHERE k_id = 2
OR k_parent = 2
OR EXISTS(
SELECT * FROM kategorier
WHERE k_parent = 2
AND k_id = k.k_parent
)
)
Förlåt, jag är ju dum i huvudet. Försöker göra för många saker samtidigt idag.
Det skall ju naturligtvis vara SELECT k_id och inte SELECT * i sub-selecten. Alltså:
SELECT posts.*, posts_rel.*, persons.person, users.username, (SELECT COUNT(*)
FROM posts_rel
WHERE p_r_parent = p_id
) has_translation
FROM posts
LEFT JOIN posts_rel
ON p_id = p_r_parent
LEFT JOIN users
ON p_creator = u_id
LEFT JOIN persons
ON p_person = p_id
WHERE NOT (p_visibility = 0)
AND p_kategori IN (
SELECT k_id FROM kategorier k
WHERE k_id = 2
OR k_parent = 2
OR EXISTS(
SELECT * FROM kategorier
WHERE k_parent = 2
AND k_id = k.k_parent
)
)
Hehe, jag hoppades att jag skulle slippa fråga igen, men nu har jag försökt i flera timmar och det blir bara sämre och sämre och sämre :P
Utöver tidigare listning så skulle jag nu vilja lista alla poster och placera dem i ul-listor under rätt kategorier. Tillbaka till ett liknande exempel som i första inlägget, men nu även med poster:
Posterna är alltid löv och jag vill inte visa huvud-/sub-/kategorier som inte har några poster. Mitt taffliga försök innehåller nu en hel drös med JOINS :(
SELECT posts.*, posts_rel.*,
kategorier.k_ordning, kategorier.k_titel, kategorier.k_id AS k_parent, kategorier.k_is_parent,
kategorier_p.k_titel AS k_titel_p, kategorier_p.k_id AS k_parent_p,
kategorier_p_p.k_titel AS k_titel_p_p, kategorier_p_p.k_id AS k_parent_p_p
FROM posts
INNER JOIN posts_rel
ON p_id = p_r_parent
INNER JOIN kategorier
ON p_kategori = k_id
INNER JOIN kategorier AS kategorier_p
ON kategorier.k_parent = kategorier_p.k_id
INNER JOIN kategorier AS kategorier_p_p
ON kategorier_p.k_parent = kategorier_p_p.k_id
WHERE person = " . $personid . "
ORDER BY k_order ASC, p_name ASC
Detta måste ju gå att lösa på något annat sätt? Jag låser åter igen in mig på att det bara funkar till nivå tre nu också ;)
Tanken med det här är att jag för varje postrad nu får fram post-namnet och alla huvud-/sub-/kategorier som tillhör varje post. Jag kan sen lista dem i rätt ordning med hjälp av fältet k_ordning och därefter i bokstavsordning p_name. Min tanke är att sen kolla om kategorin från föregående post redan har printats ut, i så fall skriver jag bara ut postnamnet, annars printar jag ut en ny kategorirubrik.
hehe, ok, håll i er! Nu har jag skridit till verket med min ovanstående kod och här följer tillhörande PHP-kod i samma kaliber!! Är jag inte söt? :e
Det flyter på förvånansvärt bra, men jag har bara drygt 100 poster i databasen än så länge också så ;)
Oerhört tacksam om någon kan leda mig i rätt riktning för att snygga till detta hehe.
Oinbjudande kod att kolla in jag vet, sorry. :) Jag vet att detta inte är PHP-forum, men det är så direkt kopplat till tidigare kod så jag tycker det var bäst. Tack!
Detta måste ju gå att lösa på något annat sätt? Jag låser åter igen in mig på att det bara funkar till nivå tre nu också ;)
Tanken med det här är att jag för varje postrad nu får fram post-namnet och alla huvud-/sub-/kategorier som tillhör varje post. Jag kan sen lista dem i rätt ordning med hjälp av fältet k_ordning och därefter i bokstavsordning p_name. Min tanke är att sen kolla om kategorin från föregående post redan har printats ut, i så fall skriver jag bara ut postnamnet, annars printar jag ut en ny kategorirubrik.
Men ärligt, hur korkat är inte denna lösning? :e
Tackar för hjälp i rätt riktning!
Jag ser inte riktigt vad du skulle ändra på. I SQL Server hade jag smackat upp det som XML direkt ur databasen, men MySql har väl inget sådant? Och då återstår ju bara att ta med kategoritexterna på varje rad, sortera och bygga upp hierarkin i kod.