• Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

Nur 5 Datensätze auslesen - MySQL

thuemmy

Aktives Mitglied
Also, wie man nur 5 Datensätze ausliest, das weiß ich schon. Mein Problem ist, dass ich eine Tabelle habe, mit mehreren (in der Zukunft) Fachbeiträgen.
Aufbau der Tabelle
Code:
id int a-i
jahr int (4)
monat int (2)
artikel text
hauptartikel bool
Wenn jetzt ein bestimmter Beitrag ausgewählt wird, möchte ich jeweils für die beiden neueren und die beiden ältern einen Ausschnitt anzeigen. Dass es nachher so, oder so ähnlich aussieht

  • Anriss Juni 2012
  • Anriss Juli 2012
  • kompletter Artikel August 2012
  • Anriss September 2012 (Hauptbeitrag)
  • Anriss September 2012
Es kann sein, dass es für einen Monat auch 2 Beiträge gibt, die werden dann über den boolwert hauptartikel ausgewertet, der Hauptartikel findet Vorrang. Zu dem Artikel, den ich komplett anzeigen will, habe ich die id.

Muss ich da 3 SELECT machen,
  1. SELECT den Beitrag den ich komplett anzeigen lassen will?
  2. SELECT die beiden (zeitlich) vorherigen Beiträge
  3. SELECT die beiden /zeitlich) späteren Beiträge
oder gibt es da eine Lösung, die mir die 5 Datensätze auf einmal liefert?
 
Werbung:
Könntest du bitte ein konkretes Beispiel geben (anhand von Beispieldaten, sowohl die Daten, die du zur Verfügung hast als auch die Struktur, die du erhalten möchstest).
 
Dein Wunsch ist mir Befehl :wink:
Code:
Tabellenaufbau
==============
id | jahr | monat | haupt | artikel                                           
 1 | 2012 |     6 | true  | Text für Juni 2012 hier kommt viel Text           
 2 | 2012 |     7 | true  | Text für Juli 2012 und noch mehr Text             
 3 | 2012 |     8 | true  | Text für August 2012 mit viel Text                
 4 | 2012 |     9 | true  | Text für September 2012 mit ganz viel Text und noch viel viel mehr Text       
 5 | 2012 |     9 | false | Text für September 2012 mit 'nem ganzen Artikel   
 6 | 2012 |    10 | true  | Text für Oktober 2012 und mir fällt jetzt nix ein 
 7 | 2012 |    11 | true  | Text für November 2012 jetzt fällt mir gar nix ein
Gegeben ist z.B. die id = 4.
Dann sollte das ganze in etwa so aussehen:

Text für Juli 2012 und noch ...

Text für August 2012 mit viel ...

Text für September 2012 mit ganz viel
Text und noch viel viel mehr Text

Text für Septenber 2012 mit 'nem ...

Text für Oktober 2012 jetzt fällt ...

Ich hoffe, dass Du verstanden hast, was ich vorhabe. Also zu dem 3. Artikel habe ich die id
 
Werbung:
Es ist schade, dass du die Daten nicht als datetime definiert hast, da könnte man mit MySQL einiges optimieren.

Mal davon abgesehen, muss ich erst ein paar Fragen stellen, um es möglicherweise nicht unnötig kompliziert zu lösen. Ist garantiert, dass es jeden Monat einen Artikel gibt? Falls nein, kann man sich auf "id" stützen, um eine chronologische Reihenfolge zu haben?
 
Abruf der Artikel, sortiert nach Datum:

Code:
SELECT id, CONCAT_WS('-',jahr, IF(LENGTH(monat)==2,monat,CONCAT('0',monat)),'01'), text
FROM artikel
WHERE haupt = 1
ORDER BY CONCAT_WS('-',jahr, IF(LENGTH(monat)==2,monat,CONCAT('0',monat)),'01') ASC

Bei der Ausgabe müsstest Du nur noch vergleichen, welcher Monat gerade angezeigt werden soll und bei diesem dann den kompletten Text anstelle des gekürzten ausgeben.
 
Es ist schade, dass du die Daten nicht als datetime definiert hast, da könnte man mit MySQL einiges optimieren.
Da das Projekt noch nicht online ist, und gerade in diesem Bereich noch nicht wirklich was passiert ist, bin ich, was die Tabellenstruktur betrifft, noch flexibel.
Mal davon abgesehen, muss ich erst ein paar Fragen stellen, um es möglicherweise nicht unnötig kompliziert zu lösen. Ist garantiert, dass es jeden Monat einen Artikel gibt?
Nein, ist es nicht. Es handelt sich um einen Kleingartenverein, und die Artikel um die es geht, die beziehen sich normalerweise auf gärtnerische Themen, den Monat betreffend. In Mitteleuropa macht man halt im Winter im Garten nichts :wink: Und in anderen Monaten kann es durchaus sein, dass mehrere Artikel vorhanden sind. Allerdings immer nur ein Artikel, der als hauptartikel gekennzeichnet ist.
Falls nein, kann man sich auf "id" stützen, um eine chronologische Reihenfolge zu haben?
Nein, kann man nicht, da nach und nach ein Archiv aufgebaut werden soll, auch eben nachträglich. Im Moment ist es so, dass immer nur ein Artikel auf der Seite ist, (reines HTML) der Rest (also ältere Artikel) schlummert in lokal gespeicherten Word-Dokumenten.
 
Werbung:
Das hatte ich befürchtet. Ich gebe dir bis morgen Abend noch 'ne Antwort, weil ich gerade irgendwie nicht ordentlich überlegen kann, weil ich für die Uni extrem viel arbeite gerade :D
 
Danke für die Nachricht, dann weiß ich erstmal Bescheid und werde mich in Geduld üben.

Gruß thuemmy
 
Werbung:
Bestimmt, dass es nicht das ist, was gefragt wurde. Ich würde es zwar auch eher nicht in der Datenbank lösen, aber dein Beispiel lädt erstmal alles und danach filterst du in PHP, das geht auch nicht ;)
 
Was ich an Deinem Vorschlag sehe, dass das Query alle Sätze auswählt, er soll aber nur den Artikel mit einer bestimmten id und jeweils die beiden, zeitlich (jahr, monat), vorhergehenden und nachfolgenden Artikel ausgeben.

Aber trotzdem danke für Deine Bemühungen. Ich habe jetzt immerhin gelernt, dass es nicht nur CONCAT gibt, sondern auch CONCAT_WS.
 
So, erster Wurf, den ich versuche, zu optimieren:

Code:
select
	id,
	datum,
	artikel
from
	t
where
	id in (
	select id from (
			(select
				t2.id
			from
				t t1
			inner join
				t t2
			on
				t1.id = 4
			where
				t2.datum <= t1.datum
			order by
				t2.datum desc
			limit 3)
		union
			(select
				t2.id
			from
				t t1
			inner join
				t t2
			on
				t1.id = 4
			where
				t2.datum > t1.datum
			order by
				t2.datum asc
			limit 2)
	) temp)
order by
	t.datum

Wobei ich mich nicht mit den Daten gestritten habe:
Code:
alter table t add datum date not null after monat;
update t set datum = concat_ws('-', jahr, monat, 1);
 
Zuletzt bearbeitet:
Werbung:
Ah, alles klar - die umgebenden Datensätze.

Code:
(
 SELECT id, CONCAT_WS('-',jahr, IF(LENGTH(monat)==2,monat,CONCAT('0',monat)),'01') date, text
 FROM artikel
 WHERE haupt = 1 AND CONCAT_WS('-',jahr, IF(LENGTH(monat)==2,monat,CONCAT('0',monat)),'01') = DATE_FORMAT(NOW(),'%Y-%m-%d')
)
UNION
(
 SELECT id, CONCAT_WS('-',jahr, IF(LENGTH(monat)==2,monat,CONCAT('0',monat)),'01') date, text
 FROM artikel
 WHERE haupt = 1 AND CONCAT_WS('-',jahr, IF(LENGTH(monat)==2,monat,CONCAT('0',monat)),'01') > DATE_FORMAT(NOW(),'%Y-%m-%d')
 LIMIT 2
)
UNION
(
 SELECT id, CONCAT_WS('-',jahr, IF(LENGTH(monat)==2,monat,CONCAT('0',monat)),'01') date, text
 FROM artikel
 WHERE haupt = 1 AND CONCAT_WS('-',jahr, IF(LENGTH(monat)==2,monat,CONCAT('0',monat)),'01') < DATE_FORMAT(NOW(),'%Y-%m-%d')
 LIMIT 2
)
ORDER BY date ASC

Zur Erklärung:
UNION dient dazu einzelne Ergebnismengen miteinander zu einem Gesamtergebnis zu verbinden. Wichtig dabei ist u.a. das alle Teilergebnismengen die selbe Spaltenanzahl haben.
Beim ersten Teilergebnis wird der Datensatz des aktuellen Monats geladen.
Beim zweiten Teilergebnis werden die 2 Datensätze mit einem neueren Monat geladen.
Beim dritten Teilergebnis wiederum die 2 Datensätze aus älteren Monaten.

Dabei gehe ich gerade nur pauschal davon aus, dass Du das aktuelle Datum direkt komplett anzeigen willst. Wenn Du einen Monat auch direkt aufrufen können möchtest, müsstest Du die WHERE-Bedingungen

Code:
CONCAT_WS('-',jahr, IF(LENGTH(monat)==2,monat,CONCAT('0',monat)),'01') = DATE_FORMAT(NOW(),'%Y-%m-%d')

Code:
CONCAT_WS('-',jahr, IF(LENGTH(monat)==2,monat,CONCAT('0',monat)),'01') > DATE_FORMAT(NOW(),'%Y-%m-%d')

Code:
CONCAT_WS('-',jahr, IF(LENGTH(monat)==2,monat,CONCAT('0',monat)),'01') < DATE_FORMAT(NOW(),'%Y-%m-%d')

an deine Bedürfnisse anpassen, z.B. auf die ID ändern und per PHP die anzuzeigende ID mit ins Statement übergeben.
 
Danke Asterixus, danke threadi für Eure Bemühungen und fertigen Lösungen. Ihr habt mir sehr weitergeholfen. Wäre gleich zu Beginn der Begriff UNION gefallen, da hätte ich mir dann selber den Kopf zerberchen können und wäre dann vielleicht auch zu einem Ergebnis gekommen. Aber so isses natürlich einfacher für mich.

Nochmals danke für die kompetente Hilfe.
 
Hatte mich vertan:

Code:
select
	id,
	artikel
from
	t
where
	id in (
	select id from (
		
			(select
				t2.id
			from
				t t1
			inner join
				t t2
			on
				t2.datum <= t1.datum and
				t2.haupt
			where
				t1.id = 4
			order by
				t2.datum desc
			limit 3)
		union
			(select
				t2.id
			from
				t t1
			inner join
				t t2
			on
				t2.datum > t1.datum and
				t2.haupt
			where
				t1.id = 4
			order by
				t2.datum asc
			limit 2)
	)temp)
order by
	t.datum
 
Werbung:
Zurück
Oben