เปรียบเทียบ DATETIME และ DATE โดยไม่สนใจช่วงเวลา


151

ฉันมีสองตารางที่คอลัมน์เป็นประเภทของ[date]DATETIME2(0)

ฉันต้องเปรียบเทียบสองเรคคอร์ดโดยส่วนวันที่ของพวกเขา (วัน + เดือน + ปี) การละทิ้งเวลาส่วน (ชั่วโมง + นาที + วินาที)

ฉันจะทำสิ่งนั้นได้อย่างไร

คำตอบ:


252

ใช้CASTเพื่อDATEชนิดข้อมูลใหม่ใน SQL Server 2008 เพื่อเปรียบเทียบเพียงส่วนวันที่:

IF CAST(DateField1 AS DATE) = CAST(DateField2 AS DATE)

61

ข้อเสียเปรียบเล็กน้อยในคำตอบของ Marc ก็คือทั้งสองฟิลด์นั้นเป็น typecast ซึ่งหมายความว่าคุณจะไม่สามารถใช้ประโยชน์จากดัชนีใด ๆ ได้

ดังนั้นหากมีความจำเป็นต้องเขียนแบบสอบถามที่สามารถได้รับประโยชน์จากดัชนีในเขตข้อมูลวันที่แล้ววิธีการ (ค่อนข้างซับซ้อน) ต่อไปนี้เป็นสิ่งที่จำเป็น

  • ฟิลด์วันที่จัดทำดัชนี (เรียกว่า DF1) จะต้องไม่ถูกแตะต้องโดยฟังก์ชันใด ๆ
  • ดังนั้นคุณต้องเปรียบเทียบ DF1 กับค่าช่วงวันที่เต็มรูปแบบสำหรับวันของ DF2
  • นั่นคือจากส่วนวันที่ของ DF2 ถึงวันที่ส่วนหลังของ DF2
  • กล่าวคือ (DF1 >= CAST(DF2 AS DATE)) AND (DF1 < DATEADD(dd, 1, CAST(DF2 AS DATE)))
  • หมายเหตุ : มันสำคัญมากที่การเปรียบเทียบคือ> = (อนุญาตความเท่าเทียมกัน) กับวันที่ของ DF2 และ (เคร่งครัด) <วันหลังจาก DF2 นอกจากนี้ผู้ประกอบการระหว่างไม่ทำงานเพราะมันช่วยให้ความเท่าเทียมกันทั้งสองด้าน

PS: วิธีอื่นของการแยกวันเท่านั้น (ใน SQL Server รุ่นเก่ากว่า) คือการใช้เล่ห์เหลี่ยมว่าวันที่จะแสดงภายในอย่างไร

  • ส่งวันที่เป็นทุ่น
  • ตัดส่วนที่เป็นเศษส่วน
  • ส่งค่ากลับไปเป็นวันที่และเวลา
  • กล่าวคือ CAST(FLOOR(CAST(DF2 AS FLOAT)) AS DATETIME)

5

แม้ว่าฉัน upvote คำตอบที่ทำเครื่องหมายว่าถูกต้อง ฉันต้องการที่จะสัมผัสกับบางสิ่งสำหรับทุกคนที่สะดุดกับเรื่องนี้

โดยทั่วไปหากคุณกรองเฉพาะค่าวันที่เพียงอย่างเดียว ไมโครซอฟท์แนะนำให้ใช้รูปแบบที่เป็นกลางภาษาหรือymdy-m-d

โปรดทราบว่าแบบฟอร์ม '2007-02-12' นั้นถือว่าเป็นภาษาที่เป็นกลางสำหรับประเภทข้อมูล DATE, DATETIME2 และ DATETIMEOFFSET

การเปรียบเทียบวันที่โดยใช้วิธีการข้างต้นนั้นง่ายมาก พิจารณาตัวอย่างต่อไปนี้ที่วางแผนไว้

--112 is ISO format 'YYYYMMDD'
declare @filterDate char(8) = CONVERT(char(8), GETDATE(), 112)

select 
    * 
from 
    Sales.Orders
where
    CONVERT(char(8), OrderDate, 112) = @filterDate

ในโลกที่สมบูรณ์แบบการหลีกเลี่ยงการดำเนินการใด ๆ กับคอลัมน์ที่ถูกกรองเพราะสิ่งนี้สามารถป้องกัน SQL Server ไม่ให้ใช้ดัชนีได้อย่างมีประสิทธิภาพ ที่กล่าวว่าหากข้อมูลที่คุณจัดเก็บเกี่ยวข้องกับวันที่และไม่ใช่เวลาเท่านั้นให้พิจารณาการจัดเก็บเหมือนกับDATETIMEเที่ยงคืนตามเวลา เพราะ:

เมื่อ SQL Server แปลงสัญพจน์เป็นชนิดของคอลัมน์ที่กรองแล้วมันจะถือว่าเป็นเวลาเที่ยงคืนเมื่อไม่มีการระบุส่วนของเวลา หากคุณต้องการให้ตัวกรองดังกล่าวส่งคืนแถวทั้งหมดจากวันที่ที่ระบุคุณต้องตรวจสอบให้แน่ใจว่าคุณเก็บค่าทั้งหมดด้วยเที่ยงคืนตามเวลา

ดังนั้นสมมติว่าคุณเกี่ยวข้องกับวันที่เท่านั้นและจัดเก็บข้อมูลของคุณเช่นนี้ แบบสอบถามด้านบนสามารถทำให้ง่ายขึ้นไปที่:

--112 is ISO format 'YYYYMMDD'
declare @filterDate char(8) = CONVERT(char(8), GETDATE(), 112)

select 
    * 
from 
    Sales.Orders
where
    OrderDate = @filterDate

3

คุณสามารถลองอันนี้

CONVERT(DATE, GETDATE()) = CONVERT(DATE,'2017-11-16 21:57:20.000')

ฉันทดสอบว่าสำหรับ MS SQL 2014 โดยใช้รหัสต่อไปนี้

select case when CONVERT(DATE, GETDATE()) = CONVERT(DATE,'2017-11-16 21:57:20.000') then 'ok'
            else '' end

-3

สำหรับการเปรียบเทียบสองวันเช่นDD / MM / YYYYเพื่อDD / MM โปรดจำไว้ว่าประเภทคอลัมน์สิ่งแรกของฟิลด์ต้องเป็น dateTime ตัวอย่าง: columnName: payment_date dataType: DateTime DateTime

หลังจากนั้นคุณสามารถเปรียบเทียบได้อย่างง่ายดาย ข้อความค้นหาคือ:

select  *  from demo_date where date >= '3/1/2015' and date <=  '3/31/2015'.

มันง่ายมาก ...... มันทดสอบแล้วว่า .....


สิ่งนี้ไม่ตอบคำถามเลย มันสืบค้นได้หนึ่งเดือนไม่ใช่วัน
เคอร์ติส Yallop

สำหรับข้อความค้นหาเดือนมีนาคมของคุณ: หากวันที่คือ '3/31/2015' เวลา 13:00 จะไม่พบคำถาม คุณควรใช้ <'4/1/2015'
เคอร์ติส Yallop

ลองพิจารณาใช้รูปแบบวันที่สากล '2015-03-01' ในแคนาดา (และที่อื่น ๆ อีกมากมาย) รูปแบบเป็นทางการคือ DD / MM / YYYY ซึ่งทำให้ทั้งสองรูปแบบไม่ชัดเจนและมีปัญหา
เคอร์ติส Yallop

คำตอบนี้ไม่ได้เกี่ยวข้องกับ 2 ตารางตามที่ร้องขอในคำถาม
เคอร์ติส Yallop

ใช่ฉันเห็นด้วย แต่ฉันแค่พิสูจน์วิธีการแก้ปัญหาไม่ใช่วิธีการแก้ปัญหาระหว่างประเทศ .. คุณต้องเปลี่ยนคำสั่งบางอย่าง ...
pankaj
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.