WHERE mit <= und >=

WHERE mit <= und >=

am 03.08.2007 18:17:44 von Christian Aigner

Ich hab gerade ein seltsames Problem und vielleicht weiß einer von
euch die Lösung.

1) Folgende SQL-Abfrage funktioniert und liefert das erwartete
Ergebnis (einige Datensätze):

SELECT *
FROM docs
WHERE doc_created_on="2007-08-03"


2) Folgende SQL-Abfrage funktioniert und liefert das erwartete
Ergebnis (etwas mehr Datensätze):

SELECT *
FROM docs
WHERE doc_created_on>="2007-08-01"
AND doc_created_on<="2007-08-03"


3) Folgende SQL-Abfrage liefert ein leeres Ergebnis (keinen
Datensatz):

SELECT *
FROM docs
WHERE doc_created_on>="2007-08-03"
AND doc_created_on<="2007-08-03"

Warum ist das so?

Das ganze läuft zur Zeit auf Windows XP
phpMyAdmin - 2.10.3-rc1
PHP Version 5.2.3
Server Version: 5.0.37-community-nt
MySQL-Client-Version: 5.0.37


mfg,
Christian

Re: WHERE mit <= und >=

am 03.08.2007 22:00:46 von Dirk Brosowski

Christian Aigner schrieb:
> Ich hab gerade ein seltsames Problem und vielleicht weiß einer von
> euch die Lösung.
>
> 1) Folgende SQL-Abfrage funktioniert und liefert das erwartete
> Ergebnis (einige Datensätze):
>
> SELECT *
> FROM docs
> WHERE doc_created_on="2007-08-03"
>
>
> 2) Folgende SQL-Abfrage funktioniert und liefert das erwartete
> Ergebnis (etwas mehr Datensätze):
>
> SELECT *
> FROM docs
> WHERE doc_created_on>="2007-08-01"
> AND doc_created_on<="2007-08-03"
>
>
> 3) Folgende SQL-Abfrage liefert ein leeres Ergebnis (keinen
> Datensatz):
>
> SELECT *
> FROM docs
> WHERE doc_created_on>="2007-08-03"
> AND doc_created_on<="2007-08-03"
>

Das liefert genau dann ein Ergebniss, wenn doc_created_on genau gleich
2007-08-03 ist, allerdings stellt sich dann noch die Frage von welchem
Typ die Spalte ist. Bei einem Timestamp müsste dann auch noch die
Uhrzeit übereinstimmen, wahrscheinlich implizit 00:00:00.

Im dem Bereich würde ich dein Problem suchen.

Grüße

Dirk

Re: WHERE mit <= und >=

am 04.08.2007 02:11:11 von Christian Aigner

On Fri, 03 Aug 2007 22:00:46 +0200, Dirk Brosowski wrote:

> Das liefert genau dann ein Ergebniss, wenn doc_created_on genau gleich
> 2007-08-03 ist,

Nun, bei mir kommt leider nichts, obwohl ich mehrere Datensätze habe, bei
denen doc_created_on gleich 2007-08-03 ist.


> allerdings stellt sich dann noch die Frage von welchem Typ
> die Spalte ist. Bei einem Timestamp müsste dann auch noch die Uhrzeit
> übereinstimmen, wahrscheinlich implizit 00:00:00.

Die Spalte ist vom Typ datetime.

Re: WHERE mit <= und >=

am 04.08.2007 13:24:07 von Dirk Brosowski

Christian Aigner schrieb:
> On Fri, 03 Aug 2007 22:00:46 +0200, Dirk Brosowski wrote:
>
>> Das liefert genau dann ein Ergebniss, wenn doc_created_on genau gleich
>> 2007-08-03 ist,
>
> Nun, bei mir kommt leider nichts, obwohl ich mehrere Datensätze habe, bei
> denen doc_created_on gleich 2007-08-03 ist.
>
>
>> allerdings stellt sich dann noch die Frage von welchem Typ
>> die Spalte ist. Bei einem Timestamp müsste dann auch noch die Uhrzeit
>> übereinstimmen, wahrscheinlich implizit 00:00:00.
>
> Die Spalte ist vom Typ datetime.

Zeig mal bitte das Ergebniss von

SELECT doc_created_on
FROM docs
WHERE doc_created_on="2007-08-03"

Und dann das gleiche mit <= und nochmal mit >=

Grüße

Dirk

Re: WHERE mit <= und >=

am 06.08.2007 10:36:00 von Christian Aigner

Am Sat, 04 Aug 2007 13:24:07 +0200, schrieb Dirk Brosowski
:

> Christian Aigner schrieb:
> > On Fri, 03 Aug 2007 22:00:46 +0200, Dirk Brosowski wrote:
> >
> >> Das liefert genau dann ein Ergebniss, wenn doc_created_on genau gleich
> >> 2007-08-03 ist,
> >
> > Nun, bei mir kommt leider nichts, obwohl ich mehrere Datensätze habe, bei
> > denen doc_created_on gleich 2007-08-03 ist.
> >
> >
> >> allerdings stellt sich dann noch die Frage von welchem Typ
> >> die Spalte ist. Bei einem Timestamp müsste dann auch noch die Uhrzeit
> >> übereinstimmen, wahrscheinlich implizit 00:00:00.
> >
> > Die Spalte ist vom Typ datetime.
>
> Zeig mal bitte das Ergebniss von
>
> SELECT doc_created_on
> FROM docs
> WHERE doc_created_on="2007-08-03"
>
> Und dann das gleiche mit <= und nochmal mit >=
>
> Grüße
>
> Dirk

Ich hab das Problem übers Wochenende ein wenig setzen lassen und heute
morgen hab ich es gelöst. Es war tatsächlich, wie schon oben erwähnt,
die Uhrzeit, die ebenfalls gespeichert wird. Daher konnte der
Vergleich allein auf das Datum nicht das gewünschte Ergebnis bringen.

So geht's:

SELECT *
FROM docs
WHERE DATE(doc_created_on) = "2007-08-03"
^^^^
liefert das richtige Ergebnis.

Danke für eure Hilfe.

LG,
Christian

Re: WHERE mit <= und >=

am 07.08.2007 21:55:07 von Dirk Brosowski

Christian Aigner schrieb:

> So geht's:
>
> SELECT *
> FROM docs
> WHERE DATE(doc_created_on) = "2007-08-03"
> ^^^^
> liefert das richtige Ergebnis.
>
> Danke für eure Hilfe.
>
> LG,
> Christian
>

Sauber! Und gute Rückmeldung.

Grüße

Dirk

Re: WHERE mit <= und >=

am 29.08.2007 17:07:09 von Thomas Rachel

Christian Aigner schrieb:

> Ich hab das Problem übers Wochenende ein wenig setzen lassen und heute
> morgen hab ich es gelöst. Es war tatsächlich, wie schon oben erwähnt,
> die Uhrzeit, die ebenfalls gespeichert wird. Daher konnte der
> Vergleich allein auf das Datum nicht das gewünschte Ergebnis bringen.
>
> So geht's:
>
> SELECT *
> FROM docs
> WHERE DATE(doc_created_on) = "2007-08-03"
> ^^^^
> liefert das richtige Ergebnis.

Kleiner Tip - falls es mal eine etwas größere Tabelle wird:

Dieser Query arbeitet ohne Indices, weil dies mit der Funktion DATE()
in der geschiebenen Form nicht funktioniert.

Von daher wäre ein Workaround der Form

.... WHERE doc_created_on BETWEEN "2007-08-03 00:00:00" AND "2007-08-03
23:59:59"


evtl. zielführender.


Thomas

Re: WHERE mit <= und >=

am 30.08.2007 19:08:40 von Claus Reibenstein

Thomas Rachel schrieb:

> Christian Aigner schrieb:
>
>> SELECT *
>> FROM docs
>> WHERE DATE(doc_created_on) = "2007-08-03"
>> ^^^^
>
> Dieser Query arbeitet ohne Indices, weil dies mit der Funktion DATE()
> in der geschiebenen Form nicht funktioniert.
>
> Von daher wäre ein Workaround der Form
>
> .... WHERE doc_created_on BETWEEN "2007-08-03 00:00:00" AND "2007-08-03
> 23:59:59"
>
> evtl. zielführender.

Wie wäre es mit

WHERE doc_created_on LIKE '2007-08-03 %'

?

Gruß. Claus

Re: WHERE mit <= und >=

am 30.08.2007 19:49:40 von Thomas Rachel

Claus Reibenstein schrieb:

> Thomas Rachel schrieb:
>
>> Von daher wäre ein Workaround der Form
>>
>> .... WHERE doc_created_on BETWEEN "2007-08-03 00:00:00" AND "2007-08-03
>> 23:59:59"
>>
>> evtl. zielführender.
>
> Wie wäre es mit
>
> WHERE doc_created_on LIKE '2007-08-03 %'
>
> ?

Wäre auch möglich. Aber dann wird evtl. der Index nicht genutzt, worum
es hier ja geht.


Mal testen:

create table tt(a datetime, b timestamp, c date, index a(a), index (b),
index (c));
insert into tt select from_unixtime(id*1000), from_unixtime(id*2000),
from_unixtime(id*3000) from files.files where id<60000;

(Anmerkung: files.files.id ist eine fortlaufende id; hier einfach als
Datenquelle mißbraucht)

select min(a),max(a),min(b),max(b),min(c),max(c) from tt\G
->
*************************** 1. row ***************************
min(a): 1970-01-01 01:16:40
max(a): 1971-11-26 11:23:20
min(b): 1970-01-01 01:33:20
max(b): 1973-10-20 21:46:40
min(c): 1970-01-01
max(c): 1975-09-15
1 row in set (0.00 sec)
-> ok, gut gespreizte Daten; Indezes sollten Verwendung finden


> explain select * from tt WHERE a between '1970-01-07 00:00:00' and
'1970-01-07 23:59:59'\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: tt
type: range
possible_keys: a
key: a
key_len: 9
ref: NULL
rows: 84
Extra: Using where
1 row in set (0.00 sec)

> explain select * from tt WHERE a LIKE '1970-01-07 %';
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: tt
type: ALL
possible_keys: a
key: NULL
key_len: NULL
ref: NULL
rows: 59999
Extra: Using where
1 row in set (0.01 sec)


-> LIKE nutzt den Index nicht. BETWEEN jedoch schon. (Analoge Ergebnsise
bei den Spalten b und c.)


Das Ganze auf

5.0.37-max-log MySQL Community Edition - Experimental (GPL)
mysql Ver 14.12 Distrib 5.0.37, for pc-linux-gnu (i686) using readline 5.0



HTH,

Thomas

Re: WHERE mit <= und >=

am 30.08.2007 22:37:09 von Claus Reibenstein

Thomas Rachel schrieb:

> Claus Reibenstein schrieb:
>
>> WHERE doc_created_on LIKE '2007-08-03 %'
>
> Wäre auch möglich. Aber dann wird evtl. der Index nicht genutzt, worum
> es hier ja geht.

Doch, da das Suchmuster nicht mit einem Wildcard beginnt.

> Mal testen:
>
> [...]
>
> 5.0.37-max-log MySQL Community Edition - Experimental (GPL)
¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯¯¯¯¯

Bitte verwende zum Testen eine halbwegs aktuelle Release und keine
Testversion.

Gruß. Claus

Re: WHERE mit <= und >=

am 31.08.2007 14:00:30 von Thomas Rachel

Claus Reibenstein schrieb:

> Thomas Rachel schrieb:
>
>> Claus Reibenstein schrieb:
>>
>>> WHERE doc_created_on LIKE '2007-08-03 %'
>> Wäre auch möglich. Aber dann wird evtl. der Index nicht genutzt, worum
>> es hier ja geht.
>
> Doch, da das Suchmuster nicht mit einem Wildcard beginnt.

Schon klar - aber immerhin: es handelt sich ja nicht um ein
(Var)char-Feld, sondern ein Date - da *könnte* man sich vorstellen, daß
es da Unterschiede gibt.


>> Mal testen:
>>
>> [...]
>>
>> 5.0.37-max-log MySQL Community Edition - Experimental (GPL)
> ¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯¯¯¯¯
>
> Bitte verwende zum Testen eine halbwegs aktuelle Release und keine
> Testversion.

Ich hab jetzt mal die AFAICS neueste Weder-Beta-noch-Alpha-Version
genommen: Server-Version ist nun "5.0.45-community-log MySQL Community
Edition (GPL)". Das Verhalten ist identisch.


Wobei ich Beta(5.1)- und Alpha(6.0)-Versionen mal außen vor gelassen
habe. Ist es bei denen anders?


Thomas

Re: WHERE mit <= und >=

am 31.08.2007 14:00:37 von Hartmut Holzgraefe

Claus Reibenstein wrote:
>>> WHERE doc_created_on LIKE '2007-08-03 %'
>> Wäre auch möglich. Aber dann wird evtl. der Index nicht genutzt, w=
orum=20
>> es hier ja geht.
>=20
> Doch, da das Suchmuster nicht mit einem Wildcard beginnt.

nicht wenn doc_created_on ein DATETIME oder TIMESTAMP
ist weil dann ja für den LIKE Vergleich erst in einen
String gewandelt werden muss ...

--=20
hartmut

Re: WHERE mit <= und >=

am 01.09.2007 10:51:49 von Claus Reibenstein

Hartmut Holzgraefe schrieb:

> Claus Reibenstein wrote:

>>>> WHERE doc_created_on LIKE '2007-08-03 %'

Wer hat das geschrieben? Bitte lass die Namen der Zitierten stehen.

>>> Wäre auch möglich. Aber dann wird evtl. der Index nicht genutzt, worum
>>> es hier ja geht.
>>
>> Doch, da das Suchmuster nicht mit einem Wildcard beginnt.
>
> nicht wenn doc_created_on ein DATETIME oder TIMESTAMP
> ist weil dann ja für den LIKE Vergleich erst in einen
> String gewandelt werden muss ...

Sicher? Im MySQL 5.1 Referenzhandbuch (deutsch) Kapitel 7.2.5
"Bereichsoptimierung" habe ich nirgends einen Hinweis gefunden, dass
diese Optimierung auf (VAR)CHAR beschränkt sei. Von daher nehme ich eher
an, dass sie auch hier greift, z.B. indem der LIKE-Ausdruck in einen
DATE(TIME)-Bereich konvertiert und danach dann selektiert wird.

Gruß. Claus

Re: WHERE mit <= und >=

am 01.09.2007 21:17:41 von Hartmut Holzgraefe

Claus Reibenstein wrote:
> Sicher? Im MySQL 5.1 Referenzhandbuch (deutsch) Kapitel 7.2.5
> "Bereichsoptimierung" habe ich nirgends einen Hinweis gefunden, dass
> diese Optimierung auf (VAR)CHAR beschränkt sei. Von daher nehme ich e=
her
> an, dass sie auch hier greift, z.B. indem der LIKE-Ausdruck in einen
> DATE(TIME)-Bereich konvertiert und danach dann selektiert wird.

andererseits ist LIKE ein STRING-Operator

http://dev.mysql.com/doc/refman/5.0/en/string-comparison-fun ctions.htm=
l

d.h. beide Operanden müssen Strings sein oder in solche
konvertiert werden. Siehe auch:

CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`d` datetime DEFAULT NULL,
`t` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `d` (`d`),
KEY `t` (`t`)
);

gefüllt mit ~1 Million Datumswerten aus 2007
sowohl in 'd' als auch 't'

DATETIME Feld mit BETWEEN

EXPLAIN select * from t1 where d between "2007-03-01" and "2007-03-31"\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t1
type: range
possible_keys: d
key: d
key_len: 9
ref: NULL
rows: 82418
Extra: Using where
1 row in set (0.00 sec)



DATETIME Feld mit LIKE

EXPLAIN select * from t1 where d like "2007-03-%"\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t1
type: ALL
possible_keys: d
key: NULL
key_len: NULL
ref: NULL
rows: 1048576
Extra: Using where
1 row in set, 1 warning (0.01 sec)



VARCHAR mit LIKE

EXPLAIN select * from t1 where t like "2007-03-%"\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t1
type: range
possible_keys: t
key: t
key_len: 33
ref: NULL
rows: 88815
Extra: Using where
1 row in set (0.00 sec)



VARCHAR mit BETWEEN

EXPLAIN select * from t1 where t between "2007-03-01" and "2007-03-31"\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t1
type: range
possible_keys: t
key: t
key_len: 33
ref: NULL
rows: 85874
Extra: Using where
1 row in set (0.00 sec)

Re: WHERE mit <= und >=

am 01.09.2007 23:16:33 von Claus Reibenstein

Hartmut Holzgraefe schrieb:

> Claus Reibenstein wrote:
>
>> Sicher? Im MySQL 5.1 Referenzhandbuch (deutsch) Kapitel 7.2.5
>> "Bereichsoptimierung" habe ich nirgends einen Hinweis gefunden, dass
>> diese Optimierung auf (VAR)CHAR beschränkt sei. Von daher nehme ich eher
>> an, dass sie auch hier greift, z.B. indem der LIKE-Ausdruck in einen
>> DATE(TIME)-Bereich konvertiert und danach dann selektiert wird.
>
> andererseits ist LIKE ein STRING-Operator
>
> http://dev.mysql.com/doc/refman/5.0/en/string-comparison-fun ctions.html
>
> d.h. beide Operanden müssen Strings sein oder in solche
> konvertiert werden.

Dort lese ich aber auch: "In MySQL, LIKE is allowed on numeric
expressions". Was ist denn DATETIME? Ist es ein String? Ist es numerisch?

Gruß. Claus

Re: WHERE mit <= und >=

am 02.09.2007 01:31:28 von Hartmut Holzgraefe

Claus Reibenstein wrote:
> Dort lese ich aber auch: "In MySQL, LIKE is allowed on numeric
> expressions". Was ist denn DATETIME? Ist es ein String? Ist es numerisc=
h?

"allowed" deshalb weil eine automatische Konvertierung auf
Strings durchgeführt wird ...