# Einträge tagesabhängig abfragen



## Sebigf (19. Juni 2006)

Hallo zusammen !

Ich habe ein Newsscript gecodet...
Nun würde ich es gerne nach Tagen sortiert ausgeben.

Beispiel:

[ Heute XX.XX.XXX ]
News1
News2
News3

[ Gestern XX.XX.XXX ]
News1
News2
News3

[ 2 Tage XX.XX.XXX ]
News1
News2
News3

Die Tabelle ist so aufgebaut:

- id
- headline
- content
- added (timestamp)


Wichtig ist mir dabei, dass nur Einträge ausgelesen werden, wenn diese zum Tag passen. Also wenn z.b. 1 Woche kein neuer Eintrag kam, sollen die Einträge ab dem letzten Eintrag eingezeigt werden, sodass nach 4 Tagen die Newsseite leer wird.

Ich hatte es bereits einmal gecodet, allerdings schon sehr lange her und auch sehr lastig... vor allem, wenn die News 10 < Tage zurücklegen...

Mir geht es eigentlich nur um die SELECT-Strategie, welche ich anwenden muss, da es bei mir immer sehr lastig war bisher 

Danke


----------



## Sven Mintel (19. Juni 2006)

Sebigf hat gesagt.:
			
		

> Also wenn z.b. 1 Woche kein neuer Eintrag kam, sollen die Einträge ab dem letzten Eintrag eingezeigt werden, sodass nach 4 Tagen die Newsseite leer wird.



Mmmh..das birgt irgendwie einen Widerspruch in sich....was denn nun, wenn nach 4 Tagen nicht neues da ist, die letzten Beiträge anzeigen, oder garnichts 

Ansonsten: MySQL bietet umfangreiche Datumsfunktionen...bspw. DAYOFYEAR() verbunden YEAR() sollte dich schnell weiterbringen.


----------



## Sebigf (19. Juni 2006)

Hehe, habe ein "nicht" vergessen  Danke für den Hinweis...

"Also wenn z.b. 1 Woche kein neuer Eintrag kam, sollen die Einträge ab dem letzten Eintrag angezeigt werden, sodass nach 4 Tagen die Newsseite nicht leer wird."

Vielleicht sollte ich das ganze einfacher formulieren...

Wenn keine neuen News hinzukamen, soll die Auslesung der Daten einfach "stoppen". Ich hoffe so ist es einfacher zu verstehen.


----------



## Sven Mintel (19. Juni 2006)

Naja...mach zuerst ein SELECT, wo du alle Beiträge holst, die in den letzten 4 Tagen erstellt wurden.
Wenn es da kein Ergebnis gibt, holst du halt die X neuesten Beiträge mit einem weiteren SELECT.

Oder du machst alles in einem Rutsch...holst alles nach Datum abwärts sortiert aus der DB.

Wenn du was dabei hast, was in den letzen 4 Tagen erstellt wurde, setzt du eine Flag und gibst es aus.

Ist die Flag nicht gesetzt, gibst du halt die X ersten Beiträge aus.


----------



## Sebigf (19. Juni 2006)

Danke für den Denkansatz.

Flag ?

Was ich mich frage, wie muss ich bei den Tagen vorgehen...
Soll ich die Tage einfach durch eine while() oder for() laufen lassen und dann entsprechend die SQL-Querys starten mit dem Wert, der durch die Schleife erzeugt wird.


----------



## Sven Mintel (19. Juni 2006)

Nö...nicht für jeden Tag ein einzelnes SELECT.

Wieviel Tage etwas her ist, sagt dir schon MySQL, wenn du es fragst 


```
SELECT TO_DAYS(NOW()) - TO_DAYS(datumsspalte) AS tagedifferenz
FROM tabelle
```

Mit Flag meine ich bspw. eine Variable, die du auf false setzt, sobald du etwas findest, was nicht älter als 4 Tage ist(bei der Auswertung des Ergebnisses mit PHP)

Du schaust dann halt nach, ob diese Flag FALSE ist, wenn du bei den älteren Beiträgen ankommst...wenn ja, dann beendest du die Auswertung, wenn nicht, gibst du ein paar alte Beiträg aus.


----------



## Sebigf (19. Juni 2006)

Mmh, interessante Query  Eigentlich könnte ich doch auch die Einträge Gruppieren mit den jeweiligen Tagessätzen, oder?

Mein Ziel ist es wie gesagt, nur ab dem Datum des letzten Eintrages alle Datensätze nach hinten durchzuarbeiten. Also wenn der letzte Post von heute gesehen am Donnerstag war, sollen Dienstag, Mittwoch und Donnerstag angezeigt werden... Sonst nichts.


----------



## Sven Mintel (19. Juni 2006)

Jo. klar kannst du das machen:

```
SELECT * from tabelle where TO_DAYS(NOW()) - TO_DAYS(datumsspalte) < 4
```


----------



## Gumbo (19. Juni 2006)

Ja das sollte möglich sein. Probier mal folgende Abfrage:
	
	
	



```
SELECT
        …
  FROM
        `tabelle`
  ORDER BY
        `datum` DESC
  WHERE
        TO_DAYS(MAX(`datum`)) - TO_DAYS(`datum`) < 3
```


----------



## Sven Mintel (19. Juni 2006)

Das zeigt aber nicht die Beiträge der letzen 3 Tage, sondern die der letzten 3 Tage seit dem letzten Eintrag.
Wurde bspw. das letzte mal Ostermontag etwas eingetragen, dann sind da noch Beiträge von Karfreitag bei... nicht grad neu, oder


----------



## Gumbo (19. Juni 2006)

Sven Mintel hat gesagt.:
			
		

> Das zeigt aber nicht die Beiträge der letzen 3 Tage, sondern die der letzten 3 Tage seit dem letzten Eintrag.
> Wurde bspw. das letzte mal Ostermontag etwas eingetragen, dann sind da noch Beiträge von Karfreitag bei... nicht grad neu, oder


Dann interpretieren wir Sebigfs Vorgabe wohl unterschiedlich.





			
				Sebigf hat gesagt.:
			
		

> Also wenn der letzte Post von heute gesehen am Donnerstag war, sollen Dienstag, Mittwoch und Donnerstag angezeigt werden... Sonst nichts.


----------



## Sven Mintel (19. Juni 2006)

scheint so...bloss...


> [ Heute XX.XX.XXX ]
> News1
> News2
> News3
> ...


...ist ja schon recht verständlich...und logisch obendrein.


----------



## Sebigf (19. Juni 2006)

Hehe... Freut mich, dass ich für viel Gesprächsstoff sorge ;-]
Ich möchte sowas hier haben: http://www.xbox2-newz.de/v2/index.php (News-Spalte... links)

Bei dieser Seite ist es so, dass wenn heute keine News gepostet worden währen, trotzdem drei Tage angezeigt werden. Nämlich Sonntag, Samstag und eben der Freitag (von heute aus gesehen...).

Und wenn heute gepostet worden währe, wie es ja auch ist, dann eben von Heute (Montag), Sonntag und Samstag...

Und das würde ich gerne in einer "flexiblen" (schnellen) Query umsetzen


----------



## Sven Mintel (19. Juni 2006)

Dann brauchst du eine GROUP BY-Klausel, mit der du erstmal die Ergebnisse nach Tagen gruppierst....und dann holst du halt die "jüngsten" 3 Gruppen.

Andernfalls kriegts du ja bspw. keine 3 Tage mit Texten, wenn bspw. heute jemand was geschrieben hat, und davor 5 Tage lang keiner etwas zu berichten hatte.


----------



## Sebigf (19. Juni 2006)

Also reden wir jetzt wieder von 2 Querys ?

- Tages-Query
- Item-Query

? Oder meinst du das zusammen in einer Query ? Hast du vielleicht ein kleines Beispiel für mich parat, wie genau du das meinst ? Währe super ;-]


----------



## Sven Mintel (19. Juni 2006)

Nö...warum, die "items" kommen ja fein nach Tagen gruppiert daher, wenn du willst.....alles mit 1 einzigem SELECT


----------



## Sebigf (19. Juni 2006)

Ui, also ich blicke nicht mehr durch 
Kannst mir nochmal helfen...

SELECT id, TO_DAYS(NOW()) - TO_DAYS(added) AS howold FROM tabelle GROUP BY howold ORDER BY howold DESC LIMIT 3

So ?


----------



## Gumbo (19. Juni 2006)

Probier’s doch einfach aus, kaputt machen kannst du nichts.

Ich glaube aber, dass MySQL dir dabei einen Strich durch die Rechnung macht. Daher probier mal Folgendes:
	
	
	



```
SELECT
        `id`,
        TO_DAYS(NOW()) - TO_DAYS(`added`) AS `age-in-days`
  FROM
        `tabelle`
  ORDER BY
        TO_DAYS(NOW()) - TO_DAYS(`added`) DESC
```
Bei der Limitierung muss aber noch was passieren.


----------



## Sven Mintel (20. Juni 2006)

Sven Mintel hat gesagt.:
			
		

> alles mit 1 einzigem SELECT




Sorry, geht wohl doch nicht ohne Sub-SELECT, es wäre also MySQL 4.1 erforderlich


----------



## Sebigf (20. Juni 2006)

Kein Thema, ich denke das lässt sich in Sachen "Serverlast" noch verkraften, oder etwa nicht ?

Ich habe mich auch direkt mal ran gemacht, aber ich habe schon wieder das nächste Problem. Ich wollte mit *GROUP BY added ORDER BY date DESC *alle Einträge mit dem Datum gruppieren, und eben die letzten 3 ausgeben. Nur leider gibt mir SQL nicht 3 verschiedene Ergebnisse aus...


```
$sql_entry_day = "SELECT UNIX_TIMESTAMP(added) AS date FROM tabelle WHERE (status = 'yes') GROUP BY added ORDER BY id DESC LIMIT 3";
$get_sql_entry_day = mysql_query($sql_entry_day) OR die(mysql_error());
while($day = mysql_fetch_array($get_sql_entry_day))
{    

}
```

Ich erhalte das Datum von heute, und zweimal vom 17. ! Wobei an diesen Tagen auch Einträge vorliegen, mit den entsprechenden Tagen dazwischen. Jedoch gibt es auch einen Eintrag am 16. und 15.. Somit müsste ja eigentlich der 16. einbezogen werden, oder nicht ?

Danke


----------



## Sebigf (20. Juni 2006)

Ah, ich habe denb Fehler gefunden.


```
GROUP BY DATE_FORMAT(added, '%d.%m.%Y')
```

Habe das DATE_FORMAT hinzugefügt. Oder gibt es einen besseren Weg ?

Danke


----------



## Gumbo (20. Juni 2006)

Ich glaube auch, dass es nur mit einer Subquery lösbar ist. Denn würde man die Ergebnisse etwa gruppieren, bekäme man nur die Daten der Gruppe, nicht aber die der einzelnen Datensätze innerhalb der Gruppe.


----------



## Sebigf (20. Juni 2006)

Ja, so läuft es auch wirklich genial einfach. Keine Ahnung, warum da nicht früher drauf gekommen bin selber. 

Noch etwas...

Ich habe jetzt ja die Base-Query (Gruppierung der Tage) und die Sub-Query (Items).
Bisher ist es so, dass ich ein Limit in die Subquery gesetzt habe, also z.B. 10.

Aber ist es auch machbar, dass ich solange die Tage durchlaufen lasse, bis ich ein "Gesamtlimit" erreicht habe ?

Sprich: Ich habe pro Tag 2 News in der DB, und ein Gesamtlimit von 10. Bisher würden ja nur 3 Tage ausgelesen, also 6 Items.... Ist es so machbar, dass ich jetzt sage, lade so viele neue Tage aus, bis die 10 Items erreicht sind ?!

Geht das ? Ich glaube mit einem Addon in der while() müsste es doch gehen, oder ?


----------



## Gumbo (20. Juni 2006)

Das würde die Abfrage gemein vereinfachen. Denn dann könntest du einfach an meinen letzten Abfragevorschlag einfach ein LIMIT 10 anhängen.


----------



## Sebigf (20. Juni 2006)

Wie meinst du das ? Welchen letzten Abfragevorschlag ?


----------



## Gumbo (20. Juni 2006)

Ich meinte Folgendes:
	
	
	



```
SELECT
        `id`,
        TO_DAYS(NOW()) - TO_DAYS(`added`) AS `age-in-days`
  FROM
        `tabelle`
  ORDER BY
        TO_DAYS(NOW()) - TO_DAYS(`added`) DESC
  LIMIT
        10
```


----------



## Sebigf (20. Juni 2006)

Aber das ist doch wieder auf die Tage bezogen, oder ?
Es geht mir ja um die Gesamtmenge bei den Items (News-Item)...


----------



## Gumbo (20. Juni 2006)

Wir scheinen uns im Kreis zu drehen. Was genau willst du denn nun?


----------



## Sebigf (20. Juni 2006)

1. Es ging mir um die Umsetzung von Tagesabschnitten. In dem Falle: fertig !

2. Mir kam die Idee, dass ich nicht sage, zeige mir 3 Tage an, sondern Zeige mir 10 News-Items (Sub-Query) an, egal ob dadurch 1 oder 5 Tage (als Block) angezeigt werden.

Verstehst du, was ich meine ?


----------



## Gumbo (20. Juni 2006)

Sebigf hat gesagt.:
			
		

> Mir kam die Idee, dass ich nicht sage, zeige mir 3 Tage an, sondern Zeige mir 10 News-Items (Sub-Query) an, egal ob dadurch 1 oder 5 Tage (als Block) angezeigt werden.


Und in welchem Punkt erfüllt mein Vorschlag dieses Kriterium nicht?


----------



## Sebigf (20. Juni 2006)

Ich glaube deine Lösung ist dafür gedacht, das ganze 10x (LIMIT 10) durchzugehen, mit den vergangenen Tagen, oder? 

Sprich: Gehe 10 Tage zurück...
Sorry, wenn ich mich irre, aber so sieht eine Lösung aus, für mich.


Hier ein Beispiel, wie es aussehen könnte...


```
[ Heute ]
# 1
# 2
# 3
# 4
[ 1 Tag ]
# 5
[ 2 Tage ]
# 6
# 7
# 8
[ 3 Tage ]
# 9
[ 4 Tage ]
# 10
```

Und eben auch so müsste es auslesbar sein:


```
[ Heute ]
# 1
# 2
# 3
# 4
[ 1 Tag ]
# 5
# 6
# 7
# 8
# 9
# 10
```

Wie du siehst, geht es um die Menge der Items (Sub-Query). Der Hintergedanke ist enstanden, als es um Layouting ging. Weil nur ein bestimmer Platz zur Verfügung stand.


----------



## Gumbo (20. Juni 2006)

Nein, mit der LIMIT-Klausel werden die auszuwählenden Datensätze beschränkt. Ein „LIMIT 10“ sorgt also dafür, dass nur zehn Datensätze ausgewählt werden. Und das ist doch genau das was du möchtest.

Eine Subquery ist übrigens etwas anderes.


----------



## Sebigf (20. Juni 2006)

Ok, also war deine Lösung für die Subquery ? Ich werde das gleich mal testen.


----------



## Gumbo (20. Juni 2006)

Eine Subquery ist eine SELECT-Abfrage in einer Abfrage. Habe ich so etwas benutzt? Lies dir doch erst einmal durch, was genau eine Subquery ist.


----------



## Sebigf (20. Juni 2006)

Danke für den Hinweis... 
Ich habs mir einmal durchgelesen. Soweit ganz simpel.

Ich bin davon ausgegangen, dass du meinst, dass ich in einer while() der Hauptquery noch eine 2. Querys starten soll...  OK, jetzt weis ich bescheid 

Ich habe noch eine Frage zur Subquery... Wie kann ich da mit PHP die Ergebnisse einzeln auslesen ?

Ich denke du meinst das mit dem Auslesen nun so, dass ich quasi 2 Ebenen habe, die jeweils alles auslesen.

1. Query (Hauptquery)
2. Query (Sub)


----------



## Sven Mintel (20. Juni 2006)

Wenn du Subselects verwendest, dann verarbeitest  du das Ergebnis wie eh und je.

Allerdings erhältst du kein Ergebnis vom Subselect....das Ergebnis eines Subselect dient dazu, Argumente für das Hauptquery zu liefern.

Subselects hat Gumbo jedoch nicht verwendet... übrigens sind diese, wie bereits erwähnt, erst ab MySQL 4.1 verfügbar... du solltest daher, bevor du versuchst, damit zu Arbeiten, sicherstellen, dass auch mindestens diese Version läuft.


----------



## Gumbo (20. Juni 2006)

Lies es dir lieber noch einmal genau durch. Denn mit einer Subquery werden Kriterien für die Hauptabfrage bestimmt.


----------



## Matthias Reitinger (20. Juni 2006)

Hallo,



			
				Sven Mintel hat gesagt.:
			
		

> Sorry, geht wohl doch nicht ohne Sub-SELECT, es wäre also MySQL 4.1 erforderlich


Das will ich jetzt mal überhört haben 

Der Vollständigkeit halber:

```
SELECT t.* FROM tabelle t
LEFT JOIN tabelle tmax ON 1
LEFT JOIN tabelle tgreater ON (tgreater.added > tmax.added)
WHERE
  tgreater.added IS NULL AND
  TO_DAYS(tmax.added) - TO_DAYS(t.added) < 3
ORDER BY
  t.added DESC;
```

Wobei ich die Lösung mit einer fixen Anzahl an Datensätzen auch besser finde. Bei der in [post=1289449]Beitrag #13[/post] verlinkten Beispielseite scheint es übrigens auch nicht anders gelöst zu sein.

Grüße, 
Matthias


----------



## Sven Mintel (20. Juni 2006)

Naja...das liefert nun aber die Einträge der letzten 3 Tage gesehen vom letzten Eintrag aus(oder täusche ich mich da:-()...das wollte er doch mittlerweile nicht mehr, sondern die Beiträge der letzten 3 Tage mit Einträgen, egal wann die waren.


----------



## Gumbo (20. Juni 2006)

Nein, mittlerweile möchte er lediglich die zehn letzten Datensätze egal welchen Datums.


----------



## Sven Mintel (20. Juni 2006)

Hätte er das gleich gesagt, hätte dieses Thema nur 1 Antwort


----------



## Gumbo (20. Juni 2006)

Ich schätze, er wollte genau dasselbe Resultat wie auf der verwiesene Webseite und wusste oder weiß noch immer nicht, wie so etwas realisiert werden kann. Wahrscheinlich weiß er selbst gar nicht genau, was er nun will.


----------



## Sebigf (20. Juni 2006)

Doch, das weis ich  Ich kann es nur schwer erklären, das ist mein Problem.

Also noch einmal:

Ich möchte z.b. 10 News ausgelesen bekommen, die Gruppiert sind nach dem Tag. Also werden alle Entrys mit dem selben Datum (Tag) in eine Gruppe gefasst und ausgegeben.

Nur weis ich nicht, wie ich die Tage einbetten soll, sodass es nach "Blöcken" aussieht wie @ xbox-newz.de

Thats it....


----------



## Matthias Reitinger (20. Juni 2006)

Hallo,



			
				Sven Mintel hat gesagt.:
			
		

> Naja...das liefert nun aber die Einträge der letzten 3 Tage gesehen vom letzten Eintrag aus(oder täusche ich mich da:-()...das wollte er doch mittlerweile nicht mehr, sondern die Beiträge der letzten 3 Tage mit Einträgen, egal wann die waren.


Dass du immer was zum meckern hast ;-]


```
SELECT t.*
FROM tabelle t
LEFT JOIN tabelle t2 ON (t2.added > t.added)
LEFT JOIN tabelle t3 ON (t3.added > t2.added)
LEFT JOIN tabelle t4 ON (t4.added > t3.added)
GROUP BY t.id
HAVING MIN(t4.added) IS NULL
ORDER BY t.added DESC
```

@Sebigf: Das Gruppieren ist in diesem Fall aber nicht Aufgabe von MySQL, sondern der weiterverarbeitenden Sprache (PHP, nehme ich mal an).

Grüße,
 Matthias


----------



## Gumbo (20. Juni 2006)

Sebigf hat gesagt.:
			
		

> Ich möchte z.b. 10 News ausgelesen bekommen, die Gruppiert sind nach dem Tag. Also werden alle Entrys mit dem selben Datum (Tag) in eine Gruppe gefasst und ausgegeben.
> 
> Nur weis ich nicht, wie ich die Tage einbetten soll, sodass es nach "Blöcken" aussieht wie @ xbox-newz.de


Das hatten wir auch schon. Hier noch einmal vereinfacht:
	
	
	



```
SELECT
        `id`,
        TO_DAYS(`added`) - TO_DAYS(`added`) AS `age-in-days`
  FROM
        `tabelle`
  ORDER BY
        `added` DESC
  LIMIT
        10
```
Die blockweise Ausgabe bekommst du wohl nur mit PHP hin:
	
	
	



```
$tmp = null;
while( $row = mysql_fetch_assoc($result) ) {
	if( $row['age-in-days'] != $tmp ) {
		if( !is_null($tmp) ) {
			echo '</ul>';
		}
		echo '<h3>'.$row['age-in-days'].' Tag(e) alte Einträge</h3>';
		echo '<ul>';
	}
	echo '<li>'.$row['id'].'</li>';
}
if( is_null($tmp) ) {
	echo '</ul>';
}
```


----------

