Jag får inte med alla tabeller

PHPportalen Forum Index » Databaser
Lägg ett bokmärke på hela tråden
Skapa nytt inlägg   Svara på inlägget Gå till sida 1, 2  Nästa
Visa föregående ämne :: Visa nästa ämne  
Startad av: Meddelande
Glitch



Medlem i: 940 dagar

Status: Offline



#741770
Inlägg Skrivet: 2017-06-25 08:17      Ämne: Jag får inte med alla tabeller Citera

Jag får bara med "topics"-tabellen när jag kör den här frågan.

KOD:
1:
SELECT 
2:
topics.*,COUNT(topics.id) AS total
3:
FROM topics
4:
JOIN forums ON topics.forum_id=forums.id 
5:
JOIN posts ON topics.id=posts.topic_id
6:
GROUP BY topics.id
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
harald_b
Moderator



Medlem i: 4660 dagar
Från: Tavesta
Status: Offline



#741771
Inlägg Skrivet: 2017-06-25 11:43      Ämne: Citera

Det borde gå att läsa av forums-tabellen också, på samma sätt som du nu läser av topics-tabellen:
KOD:
1:
SELECT
2:
forums.*,
3:
topics.*,
4:
COUNT(topics.id) AS total
5:
...


Med posts-tabellen är det knepigare.
Eftersom du har "GROUP BY topics.id" borde varje post i resultatet motsvara många poster i posts-tabellen, och då kan du bara göra olika sammanställningar på dessa.
Då är frågan: Vad vill du ha ut ur posts-tabellen?
 

_________________
R.r - Ett fritt affärssystem
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
Glitch



Medlem i: 940 dagar

Status: Offline



#741772
Inlägg Skrivet: 2017-06-25 12:57      Ämne: Citera

Jag får med "forums"-tabellen nu, men "total" blir fel. "Posts"-tabellen behöver jag nog inte.
Det jag försöker åstadkomma är att räkna antalet topics för varje forum.


KOD:
1:
SELECT forums.*,topics.*,COUNT(topics.id) AS total
2:
FROM topics
3:
JOIN forums ON forums.id=topics.forum_id
4:
GROUP BY topics.id
5:
ORDER BY forums.id
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
Koenigsegg



Medlem i: 3721 dagar

Status: Offline



#741773
Inlägg Skrivet: 2017-06-25 13:37      Ämne: Citera

Glitch skrev:
KOD:
1:
SELECT ..., COUNT(topics.id) AS total
2:
...
3:
GROUP BY topics.id

Jag gissar på att total blir 1 Smile. Stämmer det? Om du grupperar efter topics.id så får du bara ett topic-id i varje grupp.

Kan du tänka dig nåt i stil med
KOD:
1:
SELECT forum_id, COUNT(*)
2:
FROM topics
3:
GROUP BY forum_id

?
 

_________________
Aktiv frilansare inom ganska mycket som har med webben att göra Smile
Till toppen på sidan
Visa användarprofil Skicka privat meddelande MSN Messenger
Glitch



Medlem i: 940 dagar

Status: Offline



#741774
Inlägg Skrivet: 2017-06-25 13:45      Ämne: Citera

Koenigsegg skrev:

Kan du tänka dig nåt i stil med
KOD:
1:
SELECT forum_id, COUNT(*)
2:
FROM topics
3:
GROUP BY forum_id

?


Hur får jag med resten av kolumnerna i topics- och forum-tabellen?

Hur jag än gör får jag detta felmeddelande.

SELECT list is not in GROUP BY clause and contains nonaggregated column 'mindatabas.topics.id' which is not functionally dependent on columns in GROUP BY clause

Det fick jag aldrig i äldre versioner av MySQL.
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
harald_b
Moderator



Medlem i: 4660 dagar
Från: Tavesta
Status: Offline



#741775
Inlägget är accepterad som det rätta svaret Skrivet: 2017-06-25 15:17      Ämne: Citera

Nya mysql-versioner är kinkigare med vilka fält som innehåller enstaka värden och vilka som innehåller en serie med värden, vilket ofta blir fallet när man använder GROUP BY

Det hela borde gå att lösa genom att göra databasfrågan med GROUP BY till en underordnad databasfråga:

KOD:
1:
SELECT * FROM
2:
(
3:
SELECT forum_id, COUNT(*)
4:
FROM topics
5:
GROUP BY forum_id
6:
) AS a
7:
JOIN forums ON forums.id=a.forum_id


Det går även att joina in resten av kolumnerna från topics-tabellen, men då kommer varje rad i topics-tabellen generera en rad i resultatet:

KOD:
1:
...
2:
JOIN topics ON topics.forum_id=a.forum_id
 

_________________
R.r - Ett fritt affärssystem
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
Glitch



Medlem i: 940 dagar

Status: Offline



#741776
Inlägg Skrivet: 2017-06-25 15:30      Ämne: Citera

Jag tror jag fick med det jag behövde. Tack så mycket.
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
Glitch



Medlem i: 940 dagar

Status: Offline



#741777
Inlägg Skrivet: 2017-06-26 10:55      Ämne: Citera

Det går att välja MAX på alla kolumner som jag vill ha med.
Är det en bra idé?

KOD:
1:
SELECT forums.*,
2:
MAX(topics.id) AS topic_id,
3:
MAX(topics.topic) AS topic,
4:
COUNT(topics.id) AS topic_count
5:
FROM forums
6:
LEFT JOIN topics
7:
ON forums.id=topics.forum_id
8:
GROUP BY forums.id
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
harald_b
Moderator



Medlem i: 4660 dagar
Från: Tavesta
Status: Offline



#741778
Inlägg Skrivet: 2017-06-26 12:22      Ämne: Citera

MAX returnerar det största värdet i gruppen. Det finns ingen garanti att MAX(topics.id) och MAX(topics.topic) kommer returnera värden som hör i hop med samma post i topics-tabellen. Troligtvis gör de oftast inte det.

Om det är en bra idé eller inte beror på till vad och hur resultatet från databasfrågan skall användas.

Det finns ett antal olika funktioner du kan använda för att läsa av fält i en grupperad databasfråga:
https://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html
Om du förväntar dig att alla poster i gruppen skall innehålla samma värde, men databasfrågan inte kan garantera den saken, så kan använda GROUP_CONCAT(DISTINCT fältnamn). Då ser du tydligt i resultatet om det finns olika värden eller inte.
I ditt fall har jag dock svårt att tänka mig att alla poster i topics-tabellen med samma forum_id har samma värde i de övriga fälten också.
 

_________________
R.r - Ett fritt affärssystem
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
Glitch



Medlem i: 940 dagar

Status: Offline



#741779
Inlägg Skrivet: 2017-06-26 13:01      Ämne: Citera

Topics-tabellen innehåller fler rader än forums-tabellen.
Då kan jag i aldrig "joina" dessa?
Måste jag designa om tabellerna?

Det jag vill få ut är senaste "topicsen" för varje forum sorterat efter forum
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
harald_b
Moderator



Medlem i: 4660 dagar
Från: Tavesta
Status: Offline



#741783
Inlägg Skrivet: 2017-06-26 17:12      Ämne: Citera

Det är mycket möjligt att det går att få fram med en enda databasfråga, men jag har inte helt koll på hur det i så fall går till.

Jag hade nog tagit till den enkla lösningen att först köra en databasfråga som plockar fram data ur forum-tabellen, och sedan köra en databasfråga för varje forum som plockar ut senaste "topic":
KOD:
1:
SELECT *
2:
FROM topics
3:
WHERE forum_id=?
4:
ORDER BY tidkolumnen DESC
5:
LIMIT 1

Med preparerade databasfrågor går det ganska enkelt och effektivt.

Någon annan har kanske en idé om hur man syr ihop det till en enda databasfråga. Men då bör man också ta höjd för att det kunde förekomma forum utan några "topics"
 

_________________
R.r - Ett fritt affärssystem
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
Glitch



Medlem i: 940 dagar

Status: Offline



#741784
Inlägg Skrivet: 2017-06-27 06:15      Ämne: Citera

Jag tänkte det gick snabbare med en fråga istället för flera.
Har inte någon koll på detta med prestanda måste jag erkänna.
Tack för all hjälp.
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
Koenigsegg



Medlem i: 3721 dagar

Status: Offline



#741785
Inlägg Skrivet: 2017-06-27 09:54      Ämne: Citera

Det är inget självändamål att klämma in så mycket som möjligt i en enda databasfråga. Det är mycket viktigare att det som görs är logiskt, och att du om en månad eller två fortfarande förstår koden utan att behöva sitta och fundera. De största databasfrågorna behöver inte vara de bästa.

Om du är oroad över prestandan så finns det sätt att snabba upp koden, men att skriva så lite kod som möjligt behöver inte vara ett av dem Wink! Du kan cacha resultat från databasfrågor, du kan skapa avnormaliserade tabeller/cachetabeller för mellanlagring av saker och som uppdateras "ganska ofta"(vilket väl inte är helt ovanligt i forum, med ett stort forum så uppdateras kanske inte "senaste tråden"-listorna direkt efter att du skrivit ditt inlägg, etc). Du kan putsa på din databasdesign och kontrollera så att index verkligen används. Det gör skillnad om du loopar och hämtar en rad av resultatet i taget vs hämtar allt på en gång. Databasservrar kan också cacha frågeresultat..

TL;DR Att skriva själva databasfrågan är bara utkanten av en stor värld Smile
 

_________________
Aktiv frilansare inom ganska mycket som har med webben att göra Smile
Till toppen på sidan
Visa användarprofil Skicka privat meddelande MSN Messenger
harald_b
Moderator



Medlem i: 4660 dagar
Från: Tavesta
Status: Offline



#741786
Inlägg Skrivet: 2017-06-27 11:01      Ämne: Citera

Glitch skrev:
Jag tänkte det gick snabbare med en fråga istället för flera.
Har inte någon koll på detta med prestanda måste jag erkänna.
Tack för all hjälp.

Ibland kan det bli tvärt om också: Flera databasfrågor går snabbare än en dåligt optimerad.
Komplexa databasfrågor som involverar tabeller som uppdateras ofta kan vara svåra att casha.
Många databasverktyg visar hur lång tid databasfrågan tar. Det kan vara värt att titta på sådant när man försöker optimera. Men tänk på att första gången en databasfråga körs så kommer den visa helt andra tider än de efteröljande, så det kan vara värt att uppdatera data i databasen som ingår i frågan, och sedan köra databasfrågan två gånger, för att få ut all prestandainformation.

Ett kanske ännu bättre sätt att bedömma prestanda är att mäta tiden både för databasfrågan och koden som hanterar resultatet från den. Då kan du även jämföra totaltidåtgången för en respektive flera databasfrågor.
I PHP kan du använda microtime(true) för att mäta sådant.
 

_________________
R.r - Ett fritt affärssystem
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
Glitch



Medlem i: 940 dagar

Status: Offline



#741788
Inlägg Skrivet: 2017-06-29 14:33      Ämne: Citera

Tack för all respons.
Nu har jag gjort så här.
Jag loopar ut alla forum i en foreach-loop.
Inuti loopen hämtar jag senaste ämnena för varje forum och senaste användaren för varje ämne.
Gör jag rätt?


PHP:
1:
 
2:
$forums Forum::find_all();
3:
foreach($forums as $forum)
4:
{
5:
     $topic Topic::find_by_forum_id($forum->id);
6:
     $user User::find_by_id($topic->last_poster);
7:
     //Skriv ut allt här...
8:
 
Till toppen på sidan
Visa användarprofil Skicka privat meddelande
Visa tidigare inlägg:   
Skapa nytt inlägg   Svara på inlägget Gå till sida 1, 2  Nästa
PHPportalen Forum Index » Databaser
Hoppa till:  
Du kan inte skapa nya inlägg i det här forumet
Du kan inte svara på inlägg i det här forumet
Du kan inte ändra dina inlägg i det här forumet
Du kan inte ta bort dina inlägg i det här forumet
Du kan inte rösta i det här forumet
Du kan inte bifoga filer i detta forum
Du kan inte ladda ner filer från detta forum
Kontakta oss på adressen: info@phpportalen.net
Webbplatsen bygger i grunden på phpBB © 2001, 2002 phpBB Group

Modifieringar har senare gjorts i systemet av PHPportalen
Sid och logotypdesign skapad av Daren Jularic