Har varit borta från SQL-forumet ett tag nu men behöver nu lite kloka tankar runt en liten funktion jag håller på med :)
Jag tänkte jag skulle skapa en SQL-sats som visar de 3 senaste skapade trådarna/inläggen från samtliga forum på en startsida. Urvalet ska inte göra skillnad på om det är en tråd eller ett inlägg utan skall behandlas likvärdigt. Den enda styrande faktorn är när tråden/inlägget postades.
En tanke kan ju vara att sortera och plocka ut de tre senaste trådarna/inläggen från respektive tabell och sedan kör UNION på det resultatet och sedan sortera på datum i fallande ordning och plocka ut de tre första? Då får man väl med både trådar och inlägg?
Kan det fungera? Förslag på SQL-sats (alltså bara en basic) så kan jag bygga vidare på den :)
CREATE VIEW tmp AS
SELECT threadID AS ID, content, posted, posterID, forumID
FROM tblforumthread
ORDER BY posted DESC
LIMIT 3
UNION
SELECT threadReplyID AS ID, content, posted, posterID, forumID
FROM tblforumthreadreply
ORDER BY posted DESC
LIMIT 3;
SELECT * FROM tmp
ORDER BY posted DESC
LIMIT 3
En annan möjlighet är ju att ta ut de tre första av var och låta applikationsprogrammet jämföra datumen mellan de två recordset:en.
CREATE VIEW tmp AS
SELECT threadID AS ID, content, posted, posterID, forumID
FROM tblforumthread
ORDER BY posted DESC
LIMIT 3
UNION
SELECT threadReplyID AS ID, content, posted, posterID, forumID
FROM tblforumthreadreply
ORDER BY posted DESC
LIMIT 3;
SELECT * FROM tmp
ORDER BY posted DESC
LIMIT 3
Jag har inte använt CREATE VIEW tidigare men misstänker att denna funktion fungerar som en mellanlagring av informationen för den sista SQL-satsen? Kör jag den första och andra SQL-satsen separat eller körs de tillsammans?
Bör jag inte behålla threadID och threadreplyID för att kunna särkilja på om det är en tråd eller ett inlägg när jag skriver ut länken på huvudsidan. Blir ju olika om det är en tråd som inte har några inlägg mot en tråd som har inlägg.
aasah skrev:
En annan möjlighet är ju att ta ut de tre första av var och låta applikationsprogrammet jämföra datumen mellan de två recordset:en.
Jag vill helst försöka få fram det slutgiltiga resultatet i funktionen direkt.
Jag har inte använt CREATE VIEW tidigare men misstänker att denna funktion fungerar som en mellanlagring av informationen för den sista SQL-satsen? Kör jag den första och andra SQL-satsen separat eller körs de tillsammans?
Ja, bortsett ifrån att den inte försvinner av sig själv. För att ta bort den när du är klar får du skriva:
DROP TABLE tmp
Jag skulle köra dom efter varandra som två anrop. För OM något krånglar kan felmeddelandet indikera var problemet uppstod. Sedan vet jag inte om man kan ha ';' i ett PHP-databasanrop? Om du kör dom ihop måste den första avslutas så, för att SQL ska fatta att det är två satser.
Bör jag inte behålla threadID och threadreplyID för att kunna särkilja på om det är en tråd eller ett inlägg när jag skriver ut länken på huvudsidan. Blir ju olika om det är en tråd som inte har några inlägg mot en tråd som har inlägg.
Det kan du inte (såvitt jag förstår). Eftersom de mellanlagras i samma kolumn, så kan den kolumnen bara heta en sak. Då får du ha en indikator på något annat vis med... Eller köra via två recordset så du håller isär vad som är vad.
En view är ett fysiskt dataobjekt, och bör som sådant inte skapas och raderas som en del av en vanlig fråga. Man kan få problem med prestanda och riskerar transaktionskollisioner om användare 1 försöker skapa objektet (vyn) när användare 2 redan gjort det, eller så kanske användare 2 hinner radera innan användare 1 hunnit köra sin SELECT-fråga.
Om man vill använda en view så finns det dock inget som hindrar att du skapar den "en gång för alla", och använder samma view till alla frågor. Alternativt använder man en "derived table" (kallas även "unnamed view"), som fungerar som en view med livslängden begränsad till den specifika frågan.
Hur pass bra det fungerar i MySQL vet jag inte, men stödet för "derived tables" ska finnas där numera.
SELECT tmp.* FROM (SELECT threadID AS ID, content, posted, posterID, forumID
FROM tblforumthread
ORDER BY posted DESC
LIMIT 3
UNION
SELECT threadReplyID AS ID, content, posted, posterID, forumID
FROM tblforumthreadreply
ORDER BY posted DESC
LIMIT 3) as tmp
ORDER BY tmp.posted DESC
LIMIT 3
En detalj i sammanhanget är att en UNION är urtaskig för en view:s prestanda, och till vis del gäller det även med en "derived table". I det här fallet borde det inte bli något problem, dock, eftersom det är så få rader som plockas ut.
Däremot tror jag att många saker skulle bli smidigare om man lagrade alla inlägg, oavsett om de är startinlägg eller svarsinlägg, i samma tabell.
Sedan vet jag inte om man kan ha ';' i ett PHP-databasanrop? Om du kör dom ihop måste den första avslutas så, för att SQL ska fatta att det är två satser.
Det har jag faktiskt inte heller någon koll på. Kör de separat.
aasah skrev:
Det kan du inte (såvitt jag förstår). Eftersom de mellanlagras i samma kolumn, så kan den kolumnen bara heta en sak. Då får du ha en indikator på något annat vis med... Eller köra via två recordset så du håller isär vad som är vad.
Jag kan väl sätta ett tempfält till "1" om posten är threadreply och "0" om det är en huvudtråd. Det borde fungera va?
Däremot tror jag att många saker skulle bli smidigare om man lagrade alla inlägg, oavsett om de är startinlägg eller svarsinlägg, i samma tabell.
Visst skulle säkert saker bli lättare men enligt vad jag lärt mig om databasmodellering är det fel att lägga dessa två i en och samma tabell om det ska bli korrekt (avseende normalisering osv). En tråd är ett objekt och utgör en tabell. En tråd kan ha 0 till många svar. Enligt databaslogiken skall dessa då sparas ytterligare en tabell? Har jag fel?
Nej, du har inte fel, men frågan är vad som ska definieras som en tråd. En bekvämare och mer etablerad modell är att man säger att en tråd kan ha 1 till många inlägg, inte 0 till många svar. Om man utgår från det blir det inget direkt normaliseringsproblem, förutom det faktum att man kräver ett 1:(n>0)-förhållande mellan trådar och inlägg.
Man kan se det som att man trådtabellen innehåller "subject-objekt", medan inläggstabellen innehåller "content-objekt".
Man kan se det som att man trådtabellen innehåller "subject-objekt", medan inläggstabellen innehåller "content-objekt".
Jag har insett fördelarna att se på en tråd med det synsätt som du presenterar. När jag tagit fram funktioner som visar ex. 5 senaste inläggen i de olika forumen så blir SQL-satserna onödigt krångliga, enbart eftersom jag har tråd/svar uppdelade på två olika tabeller.
Synd att man ska lära sig den hårda vägen :e Dock har jag lärt mig väldigt mycket under resans gång. När jag får tid och lust får jag ta och designa om dessa databastabeller!
Det låter bra. Att göra fel och sedan strukturera om är en viktig del av systemutveckling och programmering. Det har till och med ett tjusigt namn: refactoring.
265 ms totalt · 4 externa anrop · v20260731065814-full.86ec41c2