การเปรียบเทียบวันที่ใน Oracle SQL


141

ฉันพยายามที่จะให้มันแสดงจำนวนพนักงานที่ได้รับการว่าจ้างหลังวันที่ 20 มิถุนายน 1994 แต่ฉันได้รับข้อผิดพลาดที่ระบุว่า "ตัวระบุที่ไม่ถูกต้อง" JUN 'โปรดช่วยด้วยขอบคุณ!

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

1
โปรดทราบว่าคุณสามารถใช้อย่างใดอย่างหนึ่ง> <หรือBETWEEN '' AND ''
แอนดรูว์

คำตอบ:


296

31-DEC-95ไม่ใช่สตริงหรือ20-JUN-94ไม่ใช่ พวกมันเป็นตัวเลขพร้อมสิ่งพิเศษที่เพิ่มเข้ามาในตอนท้าย นี้ควรจะเป็น'31-DEC-95'หรือ'20-JUN-94'- 'ทราบคำพูดเดียว สิ่งนี้จะช่วยให้คุณทำการเปรียบเทียบสตริง

อย่างไรก็ตามคุณไม่ได้ทำการเปรียบเทียบสตริง คุณกำลังทำเปรียบเทียบวันที่ คุณควรแปลงสตริงเป็นวันที่ โดยใช้ในตัวTO_DATE()ฟังก์ชั่นหรือตัวอักษรวัน

TO_DATE ()

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

วิธีนี้มีข้อผิดพลาดเล็กน้อยที่ไม่จำเป็น

  • ในฐานะที่เป็น a_horse_with_no_name บันทึกไว้ในความคิดเห็นDECไม่จำเป็นต้องหมายความว่าธันวาคม มันขึ้นอยู่กับคุณNLS_DATE_LANGUAGEและNLS_DATE_FORMATการตั้งค่า เพื่อให้แน่ใจว่าการเปรียบเทียบของคุณกับงานในสถานที่ใด ๆ คุณสามารถใช้รูปแบบรูปแบบวันที่และเวลา MMแทน
  • ปี '95 ไม่แน่นอน คุณรู้ว่าคุณหมายถึง 1995 แต่ถ้าเป็น '50 นั่นคือ 1950 หรือ 2050 เป็นการดีที่สุดเสมอที่จะชัดเจน
select employee_id
  from employee
 where employee_date_hired > to_date('31-12-1995','DD-MM-YYYY')

วันที่ตัวอักษร

ตัวอักษรวันที่เป็นส่วนหนึ่งของมาตรฐาน ANSI ซึ่งหมายความว่าคุณไม่จำเป็นต้องใช้ฟังก์ชันเฉพาะของออราเคิล เมื่อใช้ตัวอักษรคุณต้องระบุวันที่ของคุณในรูปแบบYYYY-MM-DDและคุณไม่สามารถรวมองค์ประกอบเวลา

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

โปรดจำไว้ว่าวันที่ประเภทข้อมูลของออราเคิลรวมถึง elemement 1995-12-31 00:00:00เวลาดังนั้นวันโดยไม่ต้องส่วนเวลาเทียบเท่ากับ

หากคุณต้องการรวมส่วนของเวลาคุณจะต้องใช้ตัวอักษรเวลาประทับซึ่งใช้รูปแบบ YYYY-MM-DD HH24:MI:SS[.FF0-9]

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

ข้อมูลเพิ่มเติม

NLS_DATE_LANGUAGEที่ได้มาจากNLS_LANGUAGEการที่ได้มาจากNLS_DATE_FORMAT NLS_TERRITORYสิ่งเหล่านี้ถูกตั้งค่าเมื่อคุณสร้างฐานข้อมูล แต่สามารถเปลี่ยนแปลงได้โดยการเปลี่ยนไฟล์พารามิเตอร์ inialization ของคุณหากจำเป็นจริงๆหรือในระดับเซสชันโดยใช้ALTER SESSIONไวยากรณ์ ตัวอย่างเช่น

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

หมายความว่า:

  • DD วันที่เป็นตัวเลขของเดือน 1 - 31
  • MM เดือนที่เป็นตัวเลขของปี 01 - 12 (มกราคมคือ 01)
  • YYYYปี 4 หลัก - ในความคิดของฉันนี้ดีกว่าเสมอ 2 ปีYYเพราะไม่มีความสับสนกับศตวรรษที่คุณกำลังอ้างถึง
  • HH24 ชั่วโมงของวัน 0 - 23
  • MI นาทีของชั่วโมง 0 - 59
  • SS วินาทีของนาที 0-59

คุณสามารถหาข้อมูลภาษาและภาษาวันที่การตั้งค่าปัจจุบันของคุณโดยการสอบถามและช่วงเสียงเต็มรูปแบบของค่าที่ถูกต้องโดยการสอบถามV$NLS_PARAMETERSsV$NLS_VALID_VALUES

อ่านเพิ่มเติม


อนึ่งหากคุณต้องการให้count(*)คุณจัดกลุ่มตามemployee_id

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

นี้จะช่วยให้คุณนับต่อ employee_id


13
+1 สำหรับการใช้รูปแบบมาสก์ใน to_date () โปรดทราบว่าสิ่งนี้ยังสามารถล้มเหลวในสภาพแวดล้อมที่แตกต่างกันเนื่องจากการตั้งค่าภาษาที่แตกต่าง DECอาจไม่ใช่เดือนที่ถูกต้องเสมอไป โดยปกติแล้วจะใช้หมายเลขแทนชื่อได้ดีกว่า
a_horse_with_no_name

1
คุณสามารถระบุเวลาด้วยตัวอักษร ANSI - คุณเพียงแค่ต้องระบุtimestampตัวอักษรแทนdateตัวอักษร: timestamp '2015-01-30 19:42:04' (เพราะใน ANSI SQL dateประเภทข้อมูลไม่ได้มีเวลาเพียงtimestampชนิดข้อมูลเท่านั้น)
a_horse_with_no_name

1
ตัวอักษรวันที่ ANSI เป็นวิธีที่รัดกุมมากเมื่อเปรียบเทียบกับการพิมพ์ TO_DATE และรูปแบบวันที่ทุกครั้ง ดีสำหรับนักพัฒนาขี้เกียจอย่างฉัน สิ่งหนึ่งที่ควรสังเกตคือความDATE 2016-04-01หมาย2016-04-01 00:00:00จริงๆ และฉันคิดว่าซินแทกซ์นี้ใช้งานได้ตั้งแต่Oracle 9iเพราะนี่คือที่ซึ่ง ANSI-SQL ถูกนำมาใช้กับ Oracle
LeOn - Han Li

1
ความคิดของฉันพัฒนาขึ้นอย่างมีนัยสำคัญในช่วง 4 ปีที่ผ่านมา @Leon :-) 'ฉันได้อัปเดตคำตอบแล้ว ฉันได้กล่าวว่าตัวอักษรวันที่ไม่ได้รวมองค์ประกอบเวลา แต่ฉันเรียกสิ่งนี้ออกมาอย่างชัดเจนมากขึ้นตามที่คุณระบุ การสนับสนุนเสริม 9i สิ้นสุดลงเกือบ 6 ปีที่แล้ว ... และเผยแพร่เมื่อ 14 ปีที่แล้ว ไม่ควรเกี่ยวข้องกับผู้ใช้ส่วนใหญ่อีกต่อไป
Ben


6

สรุป

to_char ทำงานในแบบของตัวเอง

ดังนั้น,

ใช้รูปแบบนี้YYYY-MM-DD เสมอเพื่อเปรียบเทียบแทนMM-DD-YYหรือDD-MM-YYYYหรือรูปแบบอื่น ๆ


4

คุณสามารถใช้ trunc และ to_date ดังนี้:

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

จากแบบสอบถามของคุณ:

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

ฉันคิดว่าการไม่แสดงจำนวนพนักงานที่ได้รับการว่าจ้างหลังวันที่ 20 มิถุนายน 1994 หากคุณต้องการแสดงจำนวนพนักงานคุณสามารถใช้:

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

ฉันคิดว่าวิธีที่ดีที่สุดในการเปรียบเทียบวันที่คุณสามารถใช้:

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

-4

ต้องมีเครื่องหมายคำพูดเดี่ยวตั้งแต่วันที่แปลงเป็นอักขระ

เลือก employee_id นับ (*)
จากพนักงาน
ตำแหน่ง to_char (employee_date_hired, 'DD-MON-YY')> '31 -DEC-95 ';

1
SQL นี้ใช้รูปแบบวันที่โดยนัยมันจะไม่ทำงานเสมอไป
Jon Heller

5
ใช้งานได้ดีกับการตั้งค่า NLS_ * เฉพาะของคุณซึ่งอาจไม่ทำงานกับไคลเอนต์หรือเซิร์ฟเวอร์อื่น คำตอบที่ได้รับการยอมรับอธิบายว่าทำไมรูปแบบวันที่ชัดเจนจึงสำคัญ
Jon Heller

วิธีนี้เป็นการเปรียบเทียบสตริงไม่ใช่วันที่ สตริงที่สองเริ่มต้นด้วย "3" ดังนั้นการเปรียบเทียบจึงทำงานเหมือน "ลำดับตัวอักษร" น่าสนใจการเปรียบเทียบประเภทนี้ใช้งานได้จริง (เรียงลำดับโดยบังเอิญ) หากคุณใช้รูปแบบเช่น YYYY-MM-DD แต่แน่นอนว่าจะเป็นการดีกว่าที่จะเปรียบเทียบวันที่ ...
Nick Perkins
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.