Daten in Oracle SQL vergleichen


141

Ich versuche, die Anzahl der Mitarbeiter anzuzeigen, die nach dem 20. Juni 1994 eingestellt wurden. Es wird jedoch die Fehlermeldung "JUN 'ungültige Kennung" angezeigt. Bitte helfen Sie, danke!

Select employee_id, count(*)
From Employee
Where to_char(employee_date_hired, 'DD-MON-YY') > 31-DEC-95; 

1
Beachten Sie auch, dass Sie entweder > <oderBETWEEN '' AND ''
Andrew

Antworten:


296

31-DEC-95ist keine Zeichenfolge, noch ist 20-JUN-94. Es sind Zahlen mit ein paar zusätzlichen Dingen am Ende. Dies sollte sein '31-DEC-95'oder '20-JUN-94'- beachten Sie das einfache Anführungszeichen , '. Auf diese Weise können Sie einen Zeichenfolgenvergleich durchführen.

Sie führen jedoch keinen Zeichenfolgenvergleich durch. Sie führen einen Datumsvergleich durch . Sie sollten Ihre Zeichenfolge in ein Datum umwandeln. Entweder mithilfe der integrierten TO_DATE()Funktion oder eines Datumsliteral .

MITEINANDER AUSGEHEN()

select employee_id
  from employee
 where employee_date_hired > to_date('31-DEC-95','DD-MON-YY')

Diese Methode weist einige unnötige Fallstricke auf

  • Wie a_horse_with_no_name in den Kommentaren vermerkt DEC, bedeutet dies nicht unbedingt Dezember. Es hängt von Ihren NLS_DATE_LANGUAGEund NLS_DATE_FORMATEinstellungen ab. Um sicherzustellen, dass Ihr Vergleich mit der Arbeit in einem beliebigen Gebietsschema funktioniert, können Sie stattdessen das Datums- / Uhrzeitformatmodell MM verwenden
  • Das Jahr '95 ist ungenau. Sie wissen, Sie meinen 1995, aber was ist, wenn es '50 war, ist das 1950 oder 2050? Es ist immer am besten, explizit zu sein
select employee_id
  from employee
 where employee_date_hired > to_date('31-12-1995','DD-MM-YYYY')

Datumsliterale

Ein Datumsliteral ist Teil des ANSI-Standards, dh Sie müssen keine Oracle-spezifische Funktion verwenden. Wenn Sie ein Literal verwenden, müssen Sie Ihr Datum im Format angeben YYYY-MM-DDund dürfen kein Zeitelement einfügen.

select employee_id
  from employee
 where employee_date_hired > date '1995-12-31'

Beachten Sie, dass der Oracle-Datumsdatentyp ein Zeitelement enthält, sodass das Datum ohne Zeitanteil gleich ist 1995-12-31 00:00:00.

Wenn Sie einen Zeitabschnitt einschließen möchten, müssen Sie ein Zeitstempelliteral verwenden, das das Format annimmt YYYY-MM-DD HH24:MI:SS[.FF0-9]

select employee_id
  from employee
 where employee_date_hired > timestamp '1995-12-31 12:31:02'

Weitere Informationen

NLS_DATE_LANGUAGEwird abgeleitet von NLS_LANGUAGEund NLS_DATE_FORMATwird abgeleitet von NLS_TERRITORY. Diese werden beim erstmaligen Erstellen der Datenbank festgelegt. Sie können jedoch geändert werden, indem Sie Ihre Initialisierungsparameterdatei ändern - nur wenn dies wirklich erforderlich ist - oder auf Sitzungsebene mithilfe der ALTER SESSIONSyntax. Zum Beispiel:

alter session set nls_date_format = 'DD.MM.YYYY HH24:MI:SS';

Das heisst:

  • DD numerischer Tag des Monats, 1 - 31
  • MM numerischer Monat des Jahres, 01 - 12 (Januar ist 01)
  • YYYY4-stelliges Jahr - meiner Meinung nach ist dies immer besser als ein 2-stelliges Jahr, YYda es keine Verwechslung mit dem Jahrhundert gibt, auf das Sie sich beziehen.
  • HH24 Stunde des Tages, 0 - 23
  • MI Minute der Stunde, 0 - 59
  • SS Sekunde der Minute, 0-59

Sie können Ihre aktuellen Sprach- und Datumsspracheneinstellungen durch Abfragen V$NLS_PARAMETERSsund die gesamte Bandbreite gültiger Werte durch Abfragen ermitteln V$NLS_VALID_VALUES.

Weiterführende Literatur


Übrigens, wenn Sie das wollen count(*) , müssen Sie nach gruppierenemployee_id

select employee_id, count(*)
  from employee
 where employee_date_hired > date '1995-12-31'
 group by employee_id

Dies gibt Ihnen die Anzahl pro employee_id .


13
+1 für die Verwendung einer Formatmaske in to_date (). Beachten Sie, dass dies in einer anderen Umgebung aufgrund unterschiedlicher Spracheinstellungen immer noch fehlschlagen kann. DECist nicht unbedingt immer ein gültiger Monat. Es ist normalerweise besser, Zahlen anstelle von Namen zu verwenden
a_horse_with_no_name

1
Sie können eine Zeit mit einem ANSI-Literal angeben - Sie müssen lediglich ein timestampLiteral anstelle eines dateLiteral angeben : timestamp '2015-01-30 19:42:04' (da in ANSI SQL a der dateDatentyp keine Zeit hat, nur der timestampDatentyp).
a_horse_with_no_name

1
Die ANSI-Datumsliterale sind wirklich eine übersichtliche Methode, um zu vergleichen, dass jedes Mal TO_DATE und Date-Format eingegeben werden müssen. Gut für LAZY- Entwickler wie mich. Eine Sache zu beachten ist die DATE 2016-04-01Mittel 2016-04-01 00:00:00wirklich. Und ich denke, diese Syntax funktioniert seit Oracle 9i, da hier die ANSI-SQL-Syntax in Oracle eingeführt wurde.
LeOn - Han Li

1
Mein Denken hat sich in den letzten 4 Jahren erheblich weiterentwickelt @Leon :-) 'Ich habe die Antwort aktualisiert. Ich hatte erwähnt, dass ein Datumsliteral kein Zeitelement enthält, aber ich habe dies expliziter genannt, wie Sie angegeben haben. 9i Extended Support endete vor fast 6 Jahren ... und wurde vor 14 Jahren veröffentlicht. Es sollte für die große Mehrheit der Benutzer nicht mehr relevant sein.
Ben


6

Fazit,

to_char arbeitet auf seine eigene Weise

So,

Verwenden Sie zum Vergleich immer dieses Format JJJJ-MM-TT anstelle von MM-TT-JJ oder TT-MM-JJJJ oder einem anderen Format


4

Sie können trunc und to_date wie folgt verwenden:

select TO_CHAR (g.FECHA, 'DD-MM-YYYY HH24:MI:SS') fecha_salida, g.NUMERO_GUIA, g.BOD_ORIGEN, g.TIPO_GUIA, dg.DOC_NUMERO, dg.* 
from ils_det_guia dg, ils_guia g
where dg.NUMERO_GUIA = g.NUMERO_GUIA and dg.TIPO_GUIA = g.TIPO_GUIA and dg.BOD_ORIGEN = g.BOD_ORIGEN
and dg.LAB_CODIGO = 56 
and trunc(g.FECHA) > to_date('01/02/15','DD/MM/YY')
order by g.FECHA;

2

aus Ihrer Anfrage:

Select employee_id, count(*) From Employee 
Where to_char(employee_date_hired, 'DD-MON-YY') > '31-DEC-95' 

Ich denke, es ist nicht die Anzahl der Mitarbeiter anzuzeigen, die nach dem 20. Juni 1994 eingestellt werden. Wenn Sie die Anzahl der Mitarbeiter anzeigen möchten, können Sie verwenden:

Select count(*) From Employee 
Where to_char(employee_date_hired, 'YYYMMMDDD') > 19940620 

Ich denke, für bewährte Methoden zum Vergleichen von Daten können Sie Folgendes verwenden:

employee_date_hired > TO_DATE('20-06-1994', 'DD-MM-YYYY');
or
to_char(employee_date_hired, 'YYYMMMDDD') > 19940620;

-4

Ein einfaches Anführungszeichen muss vorhanden sein, da das Datum in ein Zeichen umgewandelt wurde.

Wählen Sie employee_id, count (*).
Vom Mitarbeiter
Where to_char (employee_date_hired, 'TT-MON-JJ')> '31 -DEC-95 ';

1
Diese SQL verwendet ein implizites Datumsformat, es funktioniert nicht immer.
Jon Heller

5
Es funktioniert nur für Ihre spezifischen NLS_ * -Einstellungen einwandfrei, möglicherweise nicht für andere Clients oder Server. Die akzeptierte Antwort erklärt, warum ein explizites Datumsformat wichtig ist.
Jon Heller

Diese Methode vergleicht Zeichenfolgen und keine Datumsangaben. Die zweite Zeichenfolge beginnt mit einer "3", daher funktioniert der Vergleich wie "alphabetische Reihenfolge". Interessanterweise funktioniert diese Art des Vergleichs tatsächlich (zufällig), wenn Sie ein Format wie JJJJ-MM-TT verwenden. Aber natürlich ist es besser, Daten mit Daten zu vergleichen ...
Nick Perkins
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.