Fehler bei Datenbankabfrage (Date Problem?)
Bruzzler
- datenbank
Hallo, ich habe in meinem PHP Script folgende Abfrage:
$sql = "SELECT user_id,f_name,l_name,email,date,MAX(date) as datemax,MIN(date) as datemin FROM wp_fsq_data
WHERE datemax BETWEEN '" . date('Y-m-d', strtotime('-28 days')) . "'
AND '" . date('Y-m-d', strtotime('-13 days')) . "' GROUP BY user_id ORDER BY datemax";
Wenn ich diese Abfrage in meiner Datenbank beispielhaft ausführe mit
SELECT user_id,f_name,l_name,email,date,MAX(date) as datemax,MIN(date) as datemin
FROM wp_fsq_data WHERE datemax BETWEEN '2015-02-23 15:02:15' AND '2015-02-21 15:02:15'
GROUP BY user_id ORDER BY datemax
bekomme ich den Fehler: #1054 - Unknown column 'datemax' in 'where clause'
Wenn ich den "Where"-Teil weglasse, funktioniert die Abfrage. Das date-Feld in der DB ist vom Typ datetime und wird so gespeichert: 0000-00-00 00:00:00
Was mache ich denn falsch? Danke und Grüße
Tach!
SELECT user_id,f_name,l_name,email,date,MAX(date) as datemax,MIN(date) as datemin
> FROM wp_fsq_data WHERE datemax BETWEEN '2015-02-23 15:02:15' AND '2015-02-21 15:02:15'
> GROUP BY user_id ORDER BY datemax
bekomme ich den Fehler: #1054 - Unknown column 'datemax' in 'where clause'
Die Abarbeitungsreihenfolge der Klauseln ist: FROM (mit Joins), WHERE, GROUP BY, jetzt erst kommt das SELECT, ORDER BY, LIMIT. Das WHERE hat keine Ahnung von den Aliasnamen im SELECT. Sie können dort nicht verwendet werden. Du kannst dich da nur auf den Feldnamen beziehen. (Aliasnamen von Tabellen können angegeben werden, weil FROM ja schon behandelt wurde.)
Ich denke, eine Subquery, die zuerst gruppiert und die Max-/Min-Werte ermittelt, und das WHERE in der äußeren Query ist zielführend.
Das date-Feld in der DB ist vom Typ datetime und wird so gespeichert: 0000-00-00 00:00:00
Wohl eher nicht. Wie es gespeichert wird, ist nicht relevant. Das was du da zeigst ist das Aus- und Eingabeformat. Für den Programmierer ist nur wichtig, ob das Feld ein Datums- (und Zeit-)Typ ist oder ein String-Typ. Auf erstere kann man eine Vielzahl Datums- und Zeit-Funktionen anwenden, auf Strings nicht.
Was mache ich denn falsch?
Außer dem genannten Punkten verwendest du noch jede Menge Felder im Select, die nicht im Group-By aufgeführt sind. MySQL lässt zwar sowas zu, nimmt aber dann irgendwelche Feldinhalte aus der Gruppe der Datensätze. Das kann zu unerwünschten Ergebnissen führen. Lediglich Aggregatfunktionen (MIN, MAX, SUM, ...) können gefahrlos andere Felder verwenden.
dedlfix.
Hallo,
Die Abarbeitungsreihenfolge der Klauseln ist: FROM (mit Joins), WHERE, GROUP BY, jetzt erst kommt das SELECT, ORDER BY, LIMIT. Das WHERE hat keine Ahnung von den Aliasnamen im SELECT. Sie können dort nicht verwendet werden. Du kannst dich da nur auf den Feldnamen beziehen. (Aliasnamen von Tabellen können angegeben werden, weil FROM ja schon behandelt wurde.)
Ich möchte hier ergänzen, dass man sich mal mit HAVING beschäftigen kann:
SELECT city.location_name, city.lat, city.lon, ROUND( (acos(sin(radians(city.lat)) * sin(radians(56.0)) + cos(radians(city.lat)) * cos(radians(56.0)) * cos(radians(18.0) - (radians(city.lon)))) * 6380), 1) AS linear_distance FROM city HAVING linear_distance <= 10000 ORDER BY linear_distance
Viele Grüße Siri
Tach!
Die Abarbeitungsreihenfolge der Klauseln ist: FROM (mit Joins), WHERE, GROUP BY, jetzt erst kommt das SELECT, ORDER BY, LIMIT. Das WHERE hat keine Ahnung von den Aliasnamen im SELECT. Sie können dort nicht verwendet werden. Du kannst dich da nur auf den Feldnamen beziehen. (Aliasnamen von Tabellen können angegeben werden, weil FROM ja schon behandelt wurde.)
Ich möchte hier ergänzen, dass man sich mal mit HAVING beschäftigen kann:
Ja, das ist ein guter Hinweis. Das HAVING kommt zwischen SELECT und ORDER BY, somit kann es auf Aliasnamen und auf Ergebnisse von im Select notierten Ausdrücken zugreifen.
dedlfix.
Liebe Mitdenker, liebe Wissende, liebe Neugierige,
ja!
Ich möchte hier ergänzen, dass man sich mal mit HAVING beschäftigen kann:
SELECT city.location_name, city.lat, city.lon, ROUND( (acos(sin(radians(city.lat)) * sin(radians(56.0)) + cos(radians(city.lat)) * cos(radians(56.0)) * cos(radians(18.0) - (radians(city.lon)))) * 6380),
- AS linear_distance FROM city HAVING linear_distance <= 10000 ORDER BY linear_distance
Und ich möchte nochmals erwähnen, dass man hier zunächst erst einmal als Subselect eine "Quadratabfrage" auf die große Menge durchführen sollte, für die nur einfache Vergleiche notwendig sind.
Und im zweiten Schritt sollte man die gelieferte (kleine) Menge dann erst mit Sin() und Cos() & Co filtern.
Das kann dank Subselect selbstverständlich auch in einer SQL-Abfrage stattfinden.
Das rechnet sich spätestens, wenn die Anzahl der Datensätze in der Tabelle die 10.000 (oder 50.000, ...) überschreitet.
Spirituelle Grüße Euer Robert
Hi dedlfix,
danke für deine Antwort. Und wenn ich das Datum in Unix Timestamps ausgebe? Warum kann die Where Abfrage hier nicht "subtrahieren" bzw. größer / kleiner erkennen?
$sql = "SELECT user_id,f_name,l_name,email,date,UNIX_TIMESTAMP( NOW( ) ) - UNIX_TIMESTAMP( MAX( date ) ) AS diff
FROM wp_fsq_data WHERE 'diff' < 1209600
GROUP BY user_id
Hier werden mir wieder alle ausgegeben
Danke und Grüße
Tach!
Und wenn ich das Datum in Unix Timestamps ausgebe? Warum kann die Where Abfrage hier nicht "subtrahieren" bzw. größer / kleiner erkennen?
WHERE kann das. Aber nicht mit Aliasnamen oder Ergebnissen von Berechnungen aus dem SELECT, weil SELECT erst nach dem WHERE ausgeführt wird und diese Ergebnisse und Aliasnamen noch gar nicht vorliegen.
$sql = "SELECT user_id,f_name,l_name,email,date,UNIX_TIMESTAMP( NOW( ) ) - UNIX_TIMESTAMP( MAX( date ) ) AS diff
> FROM wp_fsq_data WHERE 'diff' < 1209600
> GROUP BY user_id
Hier werden mir wieder alle ausgegeben
'diff' ist ein String. Der wird im numerischen Kontext zu 0 und 0 ist kleiner als 1209600. Die Bedingung ist stets erfüllt.
Backticks statt einfache Anführungszeichen lösen das Problem nicht, weil es grundsätzlich nicht auf diesem Wege lösbar ist. Siehe oben.
dedlfix.
Tach!
Und wenn ich das Datum in Unix Timestamps ausgebe? Warum kann die Where Abfrage hier nicht "subtrahieren" bzw. größer / kleiner erkennen?
WHERE kann das. Aber nicht mit Aliasnamen oder Ergebnissen von Berechnungen aus dem SELECT, weil SELECT erst nach dem WHERE ausgeführt wird und diese Ergebnisse und Aliasnamen noch gar nicht vorliegen.
$sql = "SELECT user_id,f_name,l_name,email,date,UNIX_TIMESTAMP( NOW( ) ) - UNIX_TIMESTAMP( MAX( date ) ) AS diff
> > FROM wp_fsq_data WHERE 'diff' < 1209600
> > GROUP BY user_id
Hier werden mir wieder alle ausgegeben
'diff' ist ein String. Der wird im numerischen Kontext zu 0 und 0 ist kleiner als 1209600. Die Bedingung ist stets erfüllt.
Backticks statt einfache Anführungszeichen lösen das Problem nicht, weil es grundsätzlich nicht auf diesem Wege lösbar ist. Siehe oben.
dedlfix.
Ich komm hier einfach nicht weiter. Acuh wenn ich
SELECT user_id,f_name,l_name,email,date FROM wp_fsq_data
WHERE date = (SELECT MAX(date) BETWEEN '2015-02-21 15:02:15' AND '2015-02-23 15:02:15' FROM wp_fsq_data)
GROUP BY user_id
ausführe kriege ich kein Resultat. Hat jemand für mich ein konkretes Beispiel, wie die Abfrage funktionieren könnte? Danke vielmals !
Ich komm hier einfach nicht weiter. Acuh wenn ich
>
> SELECT user_id,f_name,l_name,email,date FROM wp_fsq_data
> WHERE date = (SELECT MAX(date) BETWEEN '2015-02-21 15:02:15' AND '2015-02-23 15:02:15' FROM wp_fsq_data)
> GROUP BY user_id
>
ausführe kriege ich kein Resultat.
Hallo,
wie mein Beispiel gezeigt hat, kann HAVING im Gegensatz zu WHERE mit einem Alias auf eine Tabellenspalte umgehen. Warum setzt du nicht dort an? Außerdem würde ich Roberts Hinweis aufnehmen um eventuelle Fehler durch 'date' auszuschließen.
Viele Grüße Siri
Ich komm hier einfach nicht weiter. Acuh wenn ich
> >
> > SELECT user_id,f_name,l_name,email,date FROM wp_fsq_data
> > WHERE date = (SELECT MAX(date) BETWEEN '2015-02-21 15:02:15' AND '2015-02-23 15:02:15' FROM wp_fsq_data)
> > GROUP BY user_id
> >
ausführe kriege ich kein Resultat.
Hallo,
wie mein Beispiel gezeigt hat, kann HAVING im Gegensatz zu WHERE mit einem Alias auf eine Tabellenspalte umgehen. Warum setzt du nicht dort an? Außerdem würde ich Roberts Hinweis aufnehmen um eventuelle Fehler durch 'date' auszuschließen.
Viele Grüße Siri
Habe ich:
SELECT `user_id`,`f_name`,`l_name`,`email`,`date`,MAX(`date`) as datemax,MIN(`date`) as datemin
FROM `wp_fsq_data` GROUP BY `user_id` HAVING `datemax` BETWEEN '2015-02-23 15:02:15' AND '2015-02-21 15:02:15' ORDER BY `datemax`
--> Kein Resultat
Tach!
Habe ich:
SELECT `user_id`,`f_name`,`l_name`,`email`,`date`,MAX(`date`) as datemax,MIN(`date`) as datemin
> FROM `wp_fsq_data` GROUP BY `user_id` HAVING `datemax` BETWEEN '2015-02-23 15:02:15' AND '2015-02-21 15:02:15' ORDER BY `datemax`
--> Kein Resultat
Arbeite dich schrittweise an die Ursache ran. Zuerst mal das HAVING raus. Gibt das die gewünschte (noch uneingeschränkte) Ergebnismenge?
dedlfix.
Tach!
Habe ich:
SELECT `user_id`,`f_name`,`l_name`,`email`,`date`,MAX(`date`) as datemax,MIN(`date`) as datemin
> > FROM `wp_fsq_data` GROUP BY `user_id` HAVING `datemax` BETWEEN '2015-02-23 15:02:15' AND '2015-02-21 15:02:15' ORDER BY `datemax`
--> Kein Resultat
Arbeite dich schrittweise an die Ursache ran. Zuerst mal das HAVING raus. Gibt das die gewünschte (noch uneingeschränkte) Ergebnismenge?
dedlfix.
Ja, durch
SELECT `user_id`,`f_name`,`l_name`,`email`,`date`,MAX(`date`) as datemax,MIN(`date`) as datemin
FROM `wp_fsq_data` GROUP BY `user_id` ORDER BY `datemax`
erhalte ich die uneingeschränkte Menge, gruppiert nach user_id
Tach!
Arbeite dich schrittweise an die Ursache ran. Zuerst mal das HAVING raus. Gibt das die gewünschte (noch uneingeschränkte) Ergebnismenge? Ja, durch [...] erhalte ich die uneingeschränkte Menge, gruppiert nach user_id
Und da sind auch Datensätze dabei, die auf das Kriterium passen? Du kannst ja mal die Datümer im BETWEEN in die richtige Reihenfolge bringen, erst das kleine, dann das große.
dedlfix.
Tach!
Arbeite dich schrittweise an die Ursache ran. Zuerst mal das HAVING raus. Gibt das die gewünschte (noch uneingeschränkte) Ergebnismenge? Ja, durch [...] erhalte ich die uneingeschränkte Menge, gruppiert nach user_id
Und da sind auch Datensätze dabei, die auf das Kriterium passen? Du kannst ja mal die Datümer im BETWEEN in die richtige Reihenfolge bringen, erst das kleine, dann das große.
dedlfix.
DANKE!!!!!!!!!!! Die Reihenfolge wars!!! Vielen lieben Dank
Hallo,
Wenn ich diese Abfrage in meiner Datenbank beispielhaft ausführe mit
> SELECT user_id,f_name,l_name,email,date,MAX(date) as datemax,MIN(date) as datemin
> FROM wp_fsq_data WHERE datemax BETWEEN '2015-02-23 15:02:15' AND '2015-02-21 15:02:15'
> GROUP BY user_id ORDER BY datemax
>
bekomme ich den Fehler: #1054 - Unknown column 'datemax' in 'where clause'
Max(date) liefert das höchste Datum über alle Datensätze und damit genau einen Datensatz. Willst du das überhaupt?
Viele Grüße Siri
Tach!
Max(date) liefert das höchste Datum über alle Datensätze und damit genau einen Datensatz. Willst du das überhaupt?
Das Ergebnis ist ein Datensatz je Gruppe, nicht nur einer für die gesamte Tabelle. So wie die Query jetzt aufgebaut ist, sollen wohl nur die Gruppen berücksichtigt werden, deren Max-Datum im angegebenen Zeitraum liegt.
dedlfix.
Hallo,
Wenn ich diese Abfrage in meiner Datenbank beispielhaft ausführe mit
> > SELECT user_id,f_name,l_name,email,date,MAX(date) as datemax,MIN(date) as datemin
> > FROM wp_fsq_data WHERE datemax BETWEEN '2015-02-23 15:02:15' AND '2015-02-21 15:02:15'
> > GROUP BY user_id ORDER BY datemax
> >
bekomme ich den Fehler: #1054 - Unknown column 'datemax' in 'where clause'
Max(date) liefert das höchste Datum über alle Datensätze und damit genau einen Datensatz. Willst du das überhaupt?
Viele Grüße Siri
Ja, genau das will ich. Ich möchte diejenigen User haben, deren höchstes Datum älter als 14 Tage ist, und jeden User natürlich nur einmal.
Liebe Mitdenker, liebe Wissende, liebe Neugierige,
ja!
$sql = "SELECT user_id,f_name,l_name,email,date,MAX(date) as datemax,MIN(date) as datemin FROM wp_fsq_data
> WHERE datemax BETWEEN '" . date('Y-m-d', strtotime('-28 days')) . "'
> AND '" . date('Y-m-d', strtotime('-13 days')) . "' GROUP BY user_id ORDER BY datemax";
bekomme ich den Fehler: #1054 - Unknown column 'datemax' in 'where clause'
Klar, denn unbechtet der anderen Fehler ist "date" ein Schküsselwort in MySQL http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html
folglich weiß MySQL spätetens an der Stelle ",date, MAX(date)" nichts mehr damit anzufangen. Um derartige Verwechselungen von Spaltennamen mit Schlüselwörtern zu vermeiden, kann man Spaltenamen in MySQL daher mit Backticks maskieren
Spirituelle Grüße Euer Robert
Hallo,
Klar, denn unbechtet der anderen Fehler ist "date" ein Schküsselwort in MySQL http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html
sicher? Ich lese (MySQL permits some keywords to be used as unquoted identifiers because many people previously used them.) da was anderes.
Gruß Kalk
Hallo,
Klar, denn unbechtet der anderen Fehler ist "date" ein Schküsselwort in MySQL http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html
folglich weiß MySQL spätetens an der Stelle ",date, MAX(date)" nichts mehr damit anzufangen. Um derartige Verwechselungen von Spaltennamen mit Schlüselwörtern zu vermeiden, kann man Spaltenamen in MySQL daher mit Backticks maskieren
IMHO machen den Backticks Code unübersichtlicher. In jedem Fall sind passende Spaltennamen wie z.B. "last_activity_date" die bessere Lösung.
Viele Grüße Siri
Liebe Mitdenker, liebe Wissende, liebe Neugierige,
ja!
IMHO machen den Backticks Code unübersichtlicher. In jedem Fall sind passende Spaltennamen wie z.B. "last_activity_date" die bessere Lösung.
Man sollte immer die höchstmögliche Sicherheit für die Datenintegrität wählen. Die Backticks sind zwar nicht schön und auch MySQL-eigen (andere DMBS machen das anders), aber sie verhindern Störungen des Querystrings durch versehentliche Nutzung von reservierten Bezeichnern.
Darüberhinaus sollte man Spaltenbezeichner natürlich so wählen, dass sie eben diese reservierten Bezeichner nicht treffen. Wer garantiert aber, dass in einer späteren MySQL-Version kein reserviertes Wort hinzukommt, dass dann plötzlich mit den Spaltenbezeichnern kollidiert?
Hier waren es auch nicht die reservierten Bezeichner, wie schon jemand anderes schrieb, sondern es wären Funktionsnamen gewesen. Allerdings hätte es so sein können.
Für einen Funktionsnamen fehlte ein Funktionsargument. Allerdings bin ich leider nicht ganz sicher bin, ob Funktionsnamen immer sauber an den Klammern erkannt werden können...
Spirituelle Grüße Euer Robert
Tach!
Für einen Funktionsnamen fehlte ein Funktionsargument. Allerdings bin ich leider nicht ganz sicher bin, ob Funktionsnamen immer sauber an den Klammern erkannt werden können...
Es gibt keine Referenzen auf Funktionen in MySQL. Funktionen werden immer nur aufgerufen (abgesehen von der Erstellung benutzerdefinierter Funktionen) und dabei sind die Klammern Pflicht. Es gibt aber einige Konstanten im Date/Time-Bereich, die denselben Namen haben wie Funktionen (und dasselbe Ergebnis).
dedlfix.