Toon posts:

[sql] unieke rijen nodig, distinct geeft problemen

Pagina: 1
Acties:

Verwijderd

Topicstarter
Hoi,

Mijn situatie in het kort:
ik heb 1 tabel 'fberichten' waar al mijn forumberichten in staan, met deze velden: 'tid', dat verwijst naar het bijbehorende topic en 'content' met de inhoud van het bericht. Verder natuurlijk nog irrelevante velden zoals uniek id, datum, poster, etc.

Nu wil ik een query die een lijstje maakt met van elk topic het eerste bericht.
De volgende query's lopen allemaal mis:
code:
1
SELECT * FROM fberichten GROUP BY tid DESC ORDER BY tid DESC
Hij weergeeft weliswaar van elk topic 1 bericht, maar niet het eerste. Het lijkt haast willekeurig.


code:
1
SELECT DISTINCT(tid) FROM fberichten
Hij weergeeft netjes alle unieke topics, maar de content is niet opgevraagd en is er dus ook niet uit te halen.


code:
1
SELECT DISTINCT(tid), content FROM fberichten
Nu vraag ik de content wel mee, maar werkt de distinct helemaal niet meer. Er zitten dubbele topics etc tussen.

Wie kan mij helpen, met of zonder DISTINCT, als dit vervelende probleem maar opgelost wordt.

Alvast bedankt.

  • Upsal
  • Registratie: Mei 2005
  • Laatst online: 27-08-2024
Ik heb zelf ook al eens met een soortgelijk probleem gezeten, wat ik gedaan heb is stiekem kijken hoe andere forumsoftware dit opgelost had. De oplossing bleek misschien niet super genormaliseerd te zijn, maar snel is het wel:
In mijn voorbeeld maak ik gebruik van 2 tabellen: `topics` en `posts`.
Je kunt bij de tabel met topics een extra kolommaken (INT ofzo) en die `firstpost` noemen, hierin sla je het ID op van de eerste reactie. Vervolgs kun je in je SELECT query werken met de JOIN operator om de poststabel te joinen a.h.v. het veld `firstpost`.

Misschien is het ook met een GROUP BY + HAVING op te lossen, maar dit weet ik niet zeker.

[ Voor 19% gewijzigd door Upsal op 16-07-2006 22:15 ]


  • Cyphax
  • Registratie: November 2000
  • Laatst online: 21:16

Cyphax

Moderator LNX
Je hebt ook id's aan je berichten hangen, zou het niet helpen als je dan sorteert op tid en op de id's van berichten?

Saved by the buoyancy of citrus


  • E-Vix
  • Registratie: Juni 2000
  • Laatst online: 14-02 13:05

E-Vix

Nu met sneeuw!

Niet de meest nette oplossing, maar het kan wel door met twee losse query's te werken waarvan je er eentje herhaalt:
PHP:
1
2
3
4
5
$tid = mysql_query("SELECT distinct(tid) FROM fberichten");

foreach($tid) {
$firstposts .= mysql_query("select * from fberichten where tid=".$tid." order by post desc limit 1");
}


(niet klagen over de notatie. Ik weet dat ik een aantal stappen over sla, maar zo is het wel duidelijk wat het idee is)

Failed opening '/home/users/7942/signature.inc' for inclusion (include_path='.:') in /home/www/got/userstats.php on line 25


  • OnTracK
  • Registratie: Oktober 2002
  • Laatst online: 23:43
SQL:
1
2
3
4
5
6
7
8
9
10
11
12
SELECT 
     topic_id, 
     MIN(post_id) AS first_post_id,
     post_content
FROM
     fberichten
WHERE
     1
GROUP BY
     topic_id
ORDER BY
     topic_id DESC
Wat ik eerste had werkte niet, dit moet ik nog even testen. Dit werkt ook niet...
Dit werkt volgens mij tóch wel

Ik zie nergens een manier om "het eerste bericht van een topic" te identificeren... Dus die heb ik er zelf bij verzonnen, ook zou je bijvoorbeeld de laagste datum kunnen selecteren om de eerste tevoorschijn te krijgen.

Het beste wat ik voor elkaar krijg is dit: waarbij je nog met een aparte query het bericht op moet halen. Zodra ik iets anders probeer (een subquery o.i.d. krijg ik "invalid use of group by")

@hieronder: diezelfde aanname had ik zelf ook gemaakt. Maar ik hoop dat de TS zoiets ook heeft gedaan... Ik zie alleen maar een tid (topic_id)
En ik heb dus blijkbaar niet goed gelezen. iig ik hoop dat de TS hiermee geholpen is en dat hij dit ook begrijpt. Je moet nog wel even de velden hernoemen naar je eigen naamgeving.

[ Voor 118% gewijzigd door OnTracK op 16-07-2006 23:18 ]

Not everybody wins, and certainly not everybody wins all the time.
But once you get into your boat, push off and tie into your shoes.
Then you have indeed won far more than those who have never tried.


  • Cyphax
  • Registratie: November 2000
  • Laatst online: 21:16

Cyphax

Moderator LNX
OnTracK schreef op zondag 16 juli 2006 @ 22:48:
Ik zie nergens een manier om "het eerste bericht van een topic" te identificeren... Dus die heb ik er zelf bij verzonnen, ook zou je bijvoorbeeld de laagste datum kunnen selecteren om de eerste tevoorschijn te krijgen
Geen manier om het eerste bericht van een topic te identificeren? :?
Berichten hebben een uniek ID, ik ga er even vanuit dat dat een autonummeringsveld is... dan is het bericht met het laagste ID in een topic toch de eerste? :?

Saved by the buoyancy of citrus


Verwijderd

NOFI, maar queries als
SELECT * FROM fberichten GROUP BY tid DESC ORDER BY tid DESC
of
SELECT DISTINCT(tid), content FROM fberichten
zijn zo tenenkrommend beroerd! Het feit dat MySQL 't accepteert, en er ook nog wat van probeert te maken, maakt 't nog geen echte SQL.
In 't eerste geval: wat had je verwacht in die * (=alle velden) in je select wanneer je groupt op tid (aannemend dat die tid meer dan 1x voor kan komen, anders is groupen zinloos)?
In 't 2e geval eigenlijk hetzelfde: welke content wil je? Die van 't eerste record? Of de laatste? Of alle contents voor die tid?

Ik heb geen ervaring met MySQL, maar vertel 't ding gewoon wat je wil weten, en laat 'm niet gokken naar wat 't wel 's zou kunnen zijn.

  • EdwinG
  • Registratie: Oktober 2002
  • Laatst online: 20:44
ik zou zeggen:
(niet getest, fouten voor eigen risico)
SQL:
1
2
3
4
5
SELECT f1.tid, MIN(f1.UniekID), f2.content
  FROM fberichten As f1
  INNER JOIN fberichten AS f2
    ON f2.UniekID = f1.UniekID;
  GROUP BY f1.tid


Extra velden zelf toe te voegen (als f2.veldnaam)

[ Voor 12% gewijzigd door EdwinG op 17-07-2006 10:46 . Reden: GROUP BY in plaats van DISTINCT ]

Bezoek eens een willekeurige pagina


  • DND_Roche
  • Registratie: Juli 2006
  • Laatst online: 02-01-2024
Ik ben altijd slecht geweest met inner join dus daar kan ik niet op reageren; maar moet er niet iets van een group by instaan in de bovenstaande code?

In ieder geval; dit is iets wat ik hier uitgeprobeerd heb; dit zou je antwoord moeten zijn:

SQL:
1
2
3
4
5
6
7
8
9
Select a.tid
     , b.uniek_id
     , a.content
  From fberichten a
     , (Select tid
             , Min( uniek_id) uniek_id
          From fberichten
         Group By tid) b
 Where a.uniek_id = b.uniek_id

  • P_de_B
  • Registratie: Juli 2003
  • Niet online
Je kunt hiervoor de HAVING clausule gebruiken:

SQL:
1
2
3
4
5
SELECT b1.Topicid,  B2.BerichtTekst
FROM Berichten b1
INNER JOIN Berichten b2 ON B1.Topicid = B2.Topicid 
GROUP BY b1.Topicid,B2.Berichtid, B2.Bericht
HAVING MIN(B1.Berichtid) = B2.Berichtid --alleen de laagste BerichtId per TopicId selecteren

Oops! Google Chrome could not find www.rijks%20museum.nl


  • P_de_B
  • Registratie: Juli 2003
  • Niet online
DND_Roche schreef op maandag 17 juli 2006 @ 08:00:
Ik ben altijd slecht geweest met inner join dus daar kan ik niet op reageren; maar moet er niet iets van een group by instaan in de bovenstaande code?
Wat je hier doet is ook een INNER JOIN, een impliciete INNER JOIN maar het blijft er wel 1. Het hele JOIN verhaal is eigenlijk niet moeilijk: PRG Faq: hoe werken joins?. Ik zou het eens bestuderen voor het geval je niet een INNER maar een OUTER join nodig hebt, die kun je nl. alleen op de andere manier doen.

Oops! Google Chrome could not find www.rijks%20museum.nl


  • DND_Roche
  • Registratie: Juli 2006
  • Laatst online: 02-01-2024
P_de_B schreef op maandag 17 juli 2006 @ 08:31:
[...]

Wat je hier doet is ook een INNER JOIN, een impliciete INNER JOIN maar het blijft er wel 1. Het hele JOIN verhaal is eigenlijk niet moeilijk: PRG Faq: hoe werken joins?. Ik zou het eens bestuderen voor het geval je niet een INNER maar een OUTER join nodig hebt, die kun je nl. alleen op de andere manier doen.
Ik heb me een beetje verkeerd uitgedrukt; ik bedoelde niet het gebruik van een inner join; maar het gebruik van de notatie inner join/outer join e.d.

Ik heb de FAQ vorige week (vluchtig) doorgenomen; probleem is dat na 10 jaar de eerder vermelde methode te gebruiken het bijzonder lastig is om de andere notatie te gebruiken. Zeker als ik geen werk vind waar nieuwere versies dan Oracle 8i gehanteerd wordt. Die ondersteunt deze notatie niet.

Outer joins kan ik met (+) afdwingen;

[ Voor 9% gewijzigd door DND_Roche op 17-07-2006 08:42 ]


  • EdwinG
  • Registratie: Oktober 2002
  • Laatst online: 20:44
DND_Roche schreef op maandag 17 juli 2006 @ 08:00:
Ik ben altijd slecht geweest met inner join dus daar kan ik niet op reageren; maar moet er niet iets van een group by instaan in de bovenstaande code?
Klopt, ik was gisteravond blijkbaar niet helemaal wakker.
Zoals het er nu staat zou het wel moeten werken.

Bezoek eens een willekeurige pagina


Verwijderd

Topicstarter
Tjakka!
Die van DND_Roche werkt perfect! 8)
Het vreemde is dat de query van OnTrack meestal goede resultaten weergeeft, een gelijkende query had ik ook al geprobeerd, maar niet altijd. :|
De oplossing van E-Vix was hier geen optie, omdat ik het nog ga mixen met een MATCH AGAINST. Maar voor de uitleg was dat niet echt van belang.

@Afterlife: Proberen kan geen kwaad. De stelling "Als het maar werkt" gaat me ook wat ver, maar als je zaken met een niet zo'n nette query ook foutloos werken heb ik er niks tegen.

Ik zal me ook eens wat gaan verdiepen in de havings en joins. Ik ben nog een beginner.

iig bedankt voor alle respons.
Pagina: 1