Anmelden

View Full Version : SQL Date Between möchte einfach nicht gelingen



Seiten : [1] 2

dholtmann
13-10-16, 10:59
Hallo zusammen,

ich versuche alle Daten eines bestimmten Bereichs per SQL zu lesen.

Meine Idee war:


select * from Table1 where Table1Datum between date('2016-07-01')
and date('2016-07-30')


das funktioniert leider jedoch nicht: Auswahlfehler für Feld *N.



select * from Table1 where Table1Datum >= date('2016-07-01')


funktioniert, jedoch


select * from Table1 where Table1Datum >= date('2016-07-01') and
Table1Datum >= date('2016-07-30')


funktioniert wieder nicht.
Nicht einmal das Datum vorher als String casten schafft Abhilfe.
Kann mir jemand weiterhelfen?​

Fuerchau
13-10-16, 11:12
Dann prüfe mal genau die Definition deines Table1Datum ob es wirklich vom Typ DATE ist.
Normalerweise benötigt SQL kein manuelles casten wenn das Feld tatsächlich ein Date ist und die Zeichenketten korrekt formatiert sind.

DKSPROFI
13-10-16, 12:03
Moin

wenn in deiner Datei Datumsfelder sind dann so:

select * from Datei
where Feld Between '2016-10-01' and '2016-10-01'

oder, wenn deine Felder rein Numerisch sind, dann

select * from Datei
where Feld Between 20161001 and 20161001

So geht das bei mir.

mfg

DKSPROFI

dholtmann
13-10-16, 12:25
Danke für die Antworten!

Also Date ist es definitiv, denn will ich den Wert in Numeric casten bekomme ich den Fehler:
CAST von DATE in NUMERIC nicht unterstützt.

Vllt ist noch wichtig zu erwähnen, dass ich den select auf eine View anwende, in der aus drei Einzelfeldern ein Date erzeugt wird?
Jedoch sind die Ergebnisse alle korrekte Datumsangaben.
Um DKSPROFIs Tip zu testen habe ich auch mal über Umwege in numeric gecastet.
Selbst da:


where cast(substr(cast( Table1Datum as char(10)), 1, 2) concat
substr(cast( Table1Datum as char(10)), 4, 2) concat
substr(cast( Table1Datum as char(10)), 7, 2) as Numeric(6))
between 010716 and 300716

bringt er mit den Auswahlfehler für Feld *N.

Fuerchau
13-10-16, 12:41
Das kann dann in der View begründet sein.
Schau mal ins Joblog, denn SQL ist da ggf. so gesprächig um mitzuteilen, aufwelchem Satz der Fehler denn passiert.
Ggf. versucht die View aus ungültigen Werten ein Datum zu zaubern, dass dann fehlerhaft ist.
Hierzu sei noch gesagt, dass der Optimizer ggf. gar nicht die View verwendet sondern wieder mal selber den SQL aus dem View-SQL und deinem SQL umbaut.
Der Auswahlfehler kann sich auch auf Auswahlen in der View beziehen und hat mit deinem Datum gar nichts zu tun.
Ich habe z.B. eine View mit einer Where-Klausel definiert. Die Whereklausel schränkt auf einen Mandanten ein. Mache ich nun einen "Select * from MyView where xx='yy'" wird kein Index verwendet obwohl es für die Where-Klausel der View einen Index gibt, was wiederum für irgendeinen Umbau spricht.
Sollten also in der View irgendwelche anderen Casts laufen oder ggf. ungültige Vergleiche stattfinden, führt dies zu deinem Fehler.

dholtmann
13-10-16, 16:43
Stimmt, Satz 10 sei fehlerhaft!
Dankeschön!
Kann es helfen, in der View dann per where alle Sätze auszuschließen in denen das Datum ungültig ist bzw in den Fällen ein Standard Datum zu vergeben?

BenderD
13-10-16, 17:15
... das Problem ist, dass der Query Optimizer, je nach Ausführungsplan, die Ausführungsreihenfolge ändert und dann über diese Sätze fällt. Gegenwärtig kriegt man das noch weg, wenn man die Datums-Verdreherei in eine Function auslagert und da den Ersatzwert zurückgibt - in die Function guckt die Query Engine nicht rein. Da gibt es, soweit ich das erinnere eine universelle Datumsfunction auf think400.dk, die alles mögliche kann.

D*B

B.Hauser
13-10-16, 17:24
Ich würde eine UDF (User Defined Function) definieren und diese in die View einbinden, anstatt zu versuchen das Datum manuell zu konvertieren.
In der UDF kann ein ungültiges Datum durch einen Continue Handler abgefangen werden und statt des falschen Werts ein Dummy Datum (z.B. 01.01.0001 oder 31.12.9999 oder was auch immer) ausgegeben werden.
UDFs können in SQL wie skalare Funktionen eingesetzt werden.
(Es soll übrigens auch Firmen geben, die SQL und SQL-Programmierung schulen)

Die folgende UDFs empfängt ein numerisches Datum im Format JJJJMMTT und konvertiert dieses in ein echtes Datum.
Im Fehlerfall, also bei einem ungültigen Datum wird der 01.01.0001 ausgegeben.


CREATE OR REPLACE FUNCTION YourSchema.CVTNUMTODATE
(PARDATENUM DECIMAL(8, 0))
RETURNS DATE
LANGUAGE SQLDETERMINISTIC
MODIFIES SQL DATA
CALLED ON NULL INPUT
BEGIN
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
RETURN DATE ( '0001-01-01' ) ;

RETURN DATE ( DIGITS ( PARDATENUM ) CONCAT '000000' ) ;
END ;


Birgitta

Fuerchau
13-10-16, 17:54
Die Frage ist ggf. ob das Datum erkennbar falsch ist (z.B. 0 oder 99999999).
In diesem Fall kann man das auch mit einem CASE-Ausdruck lösen und den Default oder NULL zurückgeben.

Je nach dem wie die 3 Felder definiert sind hilft ggf. auch einfach dieses:
cast('0001-01-01') as date + (JJFeld -1) years + (MMFeld - 1) months + (TTFeld - 1) days

Wenn das JJFeld 2-stellig ist, kannst du das mit einem CASE wieder geradebiegen bzw. das Startdatum anpassen. Dann gibts auch mit dem Optimizer kein Problem.

Bei der Performance mit der UDF ist das nämlich so eine Sache, insbesonders wenn man auf die UDF noch eine Whereklausel hat, da zieht nämlich kein Index.

BenderD
13-10-16, 19:26
... wenn's um Performance geht, hilft bei diskreten Werten eine Umsetztabelle, wenn das ganze in einem Programm passiert, ist es oft vorteilhaft Selektion per Extrakte (temp tables) vorzuziehen...
D*B