MySQL: Die zwei neusten jeder Kategorie mit einem Query

rellek

relativ sensationell
Teammitglied
Hallöchen,

ich möchte folgendes erreichen:
Es gibt eine Kategorientabelle. Es gibt eine Texte-Tabelle.

Nun möchte ich die zwei neusten aus jeder Kategorie auslesen. Sagen wir es gibt 3 Kategorien, die heissen a, b, c und da sind Texte drin, die heissen a1, a2, b1, b2 usw.

Jetzt werden Kategorien aber unterschiedlich schnell mit neuem Content versorgt. Deshalb ist mein Problem nicht mehr so sehr trivial.
Also ich möchte aus jeder Kategorie die zwei letzten Artikel auslesen mit möglichst nur einem Query. Ist das irgendwie möglich?

Danke! :)
 

Titus

Goldmember
IMO ließe sich das nur mit einem Timestamp ansatzweise lösen, selbst dann müsste man in PHP noch aussortieren
sonst wüsste ich nicht wie man "die letzten Zwei" bekommen soll ohne für jede Kategorie einen Query zu benötigen

das einfachste wäre wohl eine Spalte mit Markierung oder Cachetabelle zu erstellen wo die abzufagenden IDS immer beim Beitragsschreiben vorgehalten werden und dann eben darüber abgefragt werden
 

rellek

relativ sensationell
Teammitglied
Joah so eine ähnliche Lösung schwebte mir auch vor (hätte die letzten 2 IDs in je einer Spalte bei der Kategorie aufgehoben). Aber das verwarf ich dann weil das nicht flexibel genug ist, wenn jemand z.b. die letzten 5 ausgeben will. (Gedankengang: Für das Menü müssen ohnehin alle Kategorien aus der DB geholt werden, da käms auf die 2 Spalten nicht an und dann hätte man die beiden letzten IDs im RAM und kann dann "SELECT * FROM texte WHERE id IN (ids)" machen)

Wobei es mir mittlerweile sinnvoller erscheint, die Kategorien im Filesystem zu cachen. Da könnte man ja beliebig viele der letzten IDs hinterlegen. Wenn ein neuer Text hinzukommt oder jemand diese Files löscht, muss der Cache eben aktualisiert werden.
Ggf. auch das noch mit cachen, was direkt auf der Startseite zu sehen ist. Dann käme man für die Startseite sogar ganz ohne Pflicht-Querys aus (von SET NAMES mal abgesehen).
 

Chance

Member
Als Beispiel mal:

Code:
Query('SELECT id,dir,title,posts,posts_blocked,klicks,status_closed,created,updated,user,status_blocked,status_warn,status_sticky,stamp,user.user_nickname,user.user_group FROM '.DB_PREFIX.'_board_thread LEFT JOIN '.DB_PREFIX.'_user as user ON '.DB_PREFIX.'_board_thread.user=user.user_id WHERE id='.CMS_ID,__FILE__,__LINE__,1);

Ggf. könnte auch ein GROUB BY helfen...

Kannst du mal den DB Aufbau posten ?
 

rellek

relativ sensationell
Teammitglied
Wenn ich das richtig sehe, bekommst du einen letzten Artikel. In der Aufgabenstellung ist DER letzte Artikel aber ein Sonderfall vom Regelfall, wo n letzte Artikel gesucht sind.

Hier mal die Strukturen:
Code:
CREATE TABLE IF NOT EXISTS `categories` (
  `catid` int(16) NOT NULL AUTO_INCREMENT,
  `title` varchar(255) NOT NULL,
  `seoalias` varchar(255) NOT NULL,
  `parent` int(16) NOT NULL,
  `customtemplate` varchar(255) NOT NULL,
  `customcssfile` varchar(255) NOT NULL,
  `headerimage` varchar(255) NOT NULL,
  `innav` tinyint(1) NOT NULL,
  `navorder` int(16) NOT NULL,
  PRIMARY KEY (`catid`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=9 ;


CREATE TABLE IF NOT EXISTS `articles` (
  `articleid` int(16) NOT NULL AUTO_INCREMENT,
  `title` varchar(255) NOT NULL,
  `seoalias` varchar(255) NOT NULL,
  `articlecontent` mediumtext NOT NULL,
  `catid` int(16) NOT NULL,
  `customtemplate` varchar(255) NOT NULL,
  `customcssfile` varchar(255) NOT NULL,
  `headerimage` varchar(255) NOT NULL,
  PRIMARY KEY (`articleid`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=24 ;
 

Titus

Goldmember
simple ist
Code:
SELECT *
FROM articles
WHERE catid IN (1,2,3)
ORDER BY articleid DESC
LIMIT 0, 5
aber eben nicht gesucht
die frage ist jetzt wie bekommt man je cat einen?

SELECT DISTINCT auf CatID? geht nicht

IMO gehen verschachtelte SQL abfragen

Code:
SELECT *
FROM articles
WHERE articleid IN ( SELECT articleid FROM articles WHERE catid = 1 ORDER BY articleid DESC LIMIT 2 )
OR articleid IN ( SELECT articleid FROM articles WHERE catid = 2 ORDER BY articleid DESC LIMIT 2 )
OR articleid IN ( SELECT articleid FROM articles WHERE catid = 3 ORDER BY articleid DESC LIMIT 2 )

die Frage ist nur was performanter ist

ich denke ein zusätzliches Feld in articles zur markierung wäre hier hilfreich (isnew)

nach schreiben eines Artikels liest man die letzten x einfach aus und und updatet diese Spalte,
dann kann man eine simple abfrage machen
Code:
SELECT *
FROM articles
WHERE isnew = 1
AND catid IN (1,2,3)
ORDER BY articleid DESC

will man das ganze etwas flexibler müsste man die letzten artikel durchnummerieren 1,2,3,4,5
und bei WHERE isnew = 1 eben WHERE isnew IN (1,2,3,4,5) schreiben

DIe frage ist halt in welchem Verhältnis steht komplexe kategorieabfrage zu cacheaufwand, wenn am Tag(oder Stunde) 100x die Letzten Themen abgerufen werden macht es doch mehr Sinn komplexe aufgaben bei der Artikelerstellung abzuarbeiten und bei wiederkehrenden Abfragen den weg des geringesten Widerstandes zu gehen
 

rellek

relativ sensationell
Teammitglied
Nja der Cache würde nicht aktualisiert werden, wenn die Uhr sagt, dass es getan werden müsste, sondern, wenn es notwendig ist. Sprich, wenn ein neuer Text in einer Kategorie landet.

Ich fragte nur deshalb, weil nämlich mein Softwarechen ein bisschen (sehr viel) schneller fertig werden müsste, weil die aktuell verwendete Software grad ihr Limit an hochgeladenen Galerie-Grafiken erreicht hat und deshalb enorm rumlahmt. Da wär nen halbwegs okayer Query schneller gegangen als sich nen Cache auszudenken, aber sinnvoller wärs wohl schon :)
 

Titus

Goldmember
wärs dann nicht cleverer die Galerie auf trab zu bringen? (hast du nicht einen Hetzner mit Corei7 - "Serverchen"? 8| )

ich halte den einzelnen Query (mit der Vorschachtelung) ehrlich gesagt für keine geniale Idee, doch lieber einzelne Querys ausführen und ggf die IDs cachen wenn es hier einen counter geben sollte, oder am besten den query ausführen und das komplette Ergebnis in einer Datei cachen die dann ganz ohne DB geladen werden kann,
kommt halt auf die Menge der Artikel an die neu gemacht werden

ich meinte 1x pro tag einen RSS feed auszugeben da kann das auch weniger Performant sein, wenn dafür öfter was geändert wird und ja dort mehr Last erzeugt würde

hast du jedoch sehr viele Anfragen weil ggf. in einer externen Seite eingebunden wäre sicher sinnvoll hier so wenig wie möglich last zu erzeugen, das Problem an Caches ist halt immer den auch zuverlässig zu aktualisieren

siehe bei zu moderierenden Themen und nach der Freischaltung, die fehlende Aktualisierung der letzten Themen im Forencache beim vB4 ;)
 

rellek

relativ sensationell
Teammitglied
Titus' schrieb:
wärs dann nicht cleverer die Galerie auf trab zu bringen?
Ja die ist schon zu Grabe getragen, dafür lädt nun nur noch das Thumb, falls es vorher noch generiert wurde...
Titus' schrieb:
(hast du nicht einen Hetzner mit Corei7 - "Serverchen"? 8| )
Jo haben wir, aber die bekloppte Galerie hat unabhängig davon, ob die Bilder wirklich gebraucht wurden, die Bilder alle eingelesen und ggf. Thumbs generiert und bei 5000 Bildern schlägt dann eben das Memory-Limit zu. Das übrigens wegen der Sitemap (die nicht gecacht wird) schon bei 256M ist. Bei nicht ganz 2000 Artikeln, übrigens.

Dazu kommen noch Usability-Katastrophen in der aktuellen Software und deshalb wollen wir ja wechseln, auf die Soft, die ich programmiere.

RSS und Sitemap hätte ich gleichfalls wie die Kategorien für die Startseite aktualisiert, wenns notwendig ist, sprich, wenn ein neuer Artikel VÖ wird. Einmal am Tag würde bei der Sitemap z.b. wegen Google News nicht reichen, denn das ist ja ziemlich Echtzeit.
 
Oben