วิธีเลือกวันที่จากคอลัมน์วันที่และเวลา


238

ฉันมีคอลัมน์ประเภท "datetime" ที่มีค่าเช่น 2009-10-20 10:00:00

ฉันต้องการดึงวันที่ออกจาก datetime และเขียนข้อความค้นหาเช่น:

SELECT * FROM 
data 
WHERE datetime = '2009-10-20' 
ORDER BY datetime DESC

ต่อไปนี้เป็นวิธีที่ดีที่สุดที่จะทำหรือไม่

SELECT * FROM 
data 
WHERE datetime BETWEEN('2009-10-20 00:00:00' AND '2009-10-20 23:59:59')
ORDER BY datetime DESC

อย่างไรก็ตามจะส่งคืนชุดผลลัพธ์ที่ว่างเปล่า ข้อเสนอแนะใด ๆ

คำตอบ:


456

คุณสามารถใช้DATE()ฟังก์ชั่นของ MySQL :

WHERE DATE(datetime) = '2009-10-20'

คุณสามารถลองสิ่งนี้:

WHERE datetime LIKE '2009-10-20%'

ดูคำตอบนี้LIKEสำหรับข้อมูลเกี่ยวกับผลกระทบของการใช้ประสิทธิภาพ


2
ลองอันนี้: ที่ไหน DATE (datetime) = '2009-10-20', มันทำงานได้
mysqllearner

44
คนแรกช้ามากและไม่สนใจดัชนี จะดีกว่าถ้ามี 'วันที่%' เช่น
kachar

วันที่ (วันที่และเวลา) ต้องการ '% keyword%' มันทำงานขอบคุณ
silvia zulinka

2
ฉันเชื่อว่านี่จะไม่ทำงานอย่างที่คาดไว้ถ้าเขตเวลา Rails เป็นอย่างอื่นที่ไม่ใช่ UTC นี่เป็นเพราะ DATE () แก้ไขค่าคอลัมน์เป็น UTC ดังนั้นวันเช่น "Fri, 30 Dec 2016 00:00:00 SGT +08: 00" ซึ่งเราคาดว่าจะพบถ้าเราถาม "2016-12-30" จะไม่พบ ทำไม? เนื่องจาก DATE () จะแก้ไขเป็น UTC เทียบเท่าก่อนทำการเปรียบเทียบซึ่งก็คือ "2016-12-29 16:00:00 UTC" แก้ไขฉันถ้าฉันผิดเพราะนี่เป็น gotcha ให้ฉันจนกระทั่งเมื่อไม่นานมานี้
Tikiboy

WHERE DATE (datetime) = '{? sdate} ทำงานได้อย่างสมบูรณ์แบบสำหรับพารามิเตอร์ Crystal Reports! เยี่ยมมาก!
MikeMighty

94

ใช้มีปัญหาประสิทธิภาพการทำงานWHERE DATE(datetime) = '2009-10-20' ตามที่ระบุไว้ที่นี่ :

  • มันจะคำนวณDATE()สำหรับทุกแถวรวมถึงแถวที่ไม่ตรงกัน
  • มันจะทำให้เป็นไปไม่ได้ที่จะใช้ดัชนีสำหรับแบบสอบถาม

ใช้BETWEENหรือ>, <, =ผู้ประกอบการที่อนุญาตให้มีการใช้ดัชนี:

SELECT * FROM data 
WHERE datetime BETWEEN '2009-10-20 00:00:00' AND '2009-10-20 23:59:59'

ปรับปรุง: ผลกระทบเกี่ยวกับการใช้LIKEแทนของผู้ประกอบการในคอลัมน์ที่จัดทำดัชนีอยู่ในระดับสูง นี่คือผลการทดสอบบางส่วนในตารางที่มี 1,176,000 แถว:

  • using datetime LIKE '2009-10-20%'=> 2931ms
  • ใช้datetime >= '2009-10-20 00:00:00' AND datetime <= '2009-10-20 23:59:59'=> 168ms

เมื่อทำการเรียกครั้งที่สองผ่านการสืบค้นเดียวกันความแตกต่างก็ยิ่งสูงขึ้น: 2984ms เทียบกับ 7ms (ใช่เพียง 7 มิลลิวินาที!) ฉันพบสิ่งนี้ในขณะที่เขียนรหัสเก่าบางรายการในโครงการโดยใช้ Hibernate


น่าสนใจหากการใช้งาน MySql แปลงDATE(datetime)เป็นBETWEEN AND พฤติกรรมโดยอัตโนมัติเราจะได้รับคำสั่งสั้น ๆ และประสิทธิภาพที่ยอดเยี่ยม ทำไมจะไม่ล่ะ? ทำไมพวกเขาไม่ทำเช่นนี้? :)
Cherry

เพราะสิ่งที่ชอบDATE(datetime) in (:list)ไม่ทำงานด้วยBETWEEN
ทิม

25

คุณสามารถจัดรูปแบบวันที่และเวลาไปยังส่วน YMD:

DATE_FORMAT(datetime, '%Y-%m-%d')

2
และด้วยวิธีนี้คุณจะได้รับเฉพาะช่วงเวลาหากจำเป็น:DATE_FORMAT(datetime, '%H:%i:%S')
Metafaniel

มันใช้งานได้ดีในการจัดรูปแบบวันที่และเวลา แต่ในทางกลับกันฐานข้อมูลจะส่งกลับอาร์เรย์ใหม่เพื่อตั้งชื่อให้มันเพียงแค่โฆษณาชื่อที่ต้องการในตอนท้าย DATE_FORMAT (columnName, '% Y-% m-% d') arrayName สำหรับรายละเอียดเพิ่มเติม เอกสารdev.mysql.com/doc/refman/8.0/en/…
Ridha Rezzag

15

แม้ว่าคำตอบทั้งหมดในหน้าจะส่งคืนผลลัพธ์ที่ต้องการ แต่ก็มีปัญหาด้านประสิทธิภาพ อย่าทำการคำนวณบนฟิลด์ในส่วนWHEREคำสั่ง (รวมถึงการDATE()คำนวณ) เนื่องจากต้องทำการคำนวณในทุกแถวในตาราง

การBETWEEN ... ANDสร้างรวมอยู่ในเงื่อนไขเส้นขอบทั้งสองกำหนดให้ระบุไวยากรณ์ 23:59:59 ณ วันที่สิ้นสุดซึ่งมีปัญหาอื่น ๆ (ธุรกรรม microsecond ซึ่งฉันเชื่อว่า MySQL ไม่รองรับในปี 2009 เมื่อมีการถามคำถาม)

วิธีที่เหมาะสมในการสืบค้นข้อมูล MySQL timestampสำหรับวันใดวันหนึ่งคือการตรวจสอบมากกว่า - เท่ากับ - เปรียบเทียบกับวันที่ต้องการและน้อยกว่าสำหรับวันหลังจากไม่ระบุชั่วโมง

WHERE datetime>='2009-10-20' AND datetime<'2009-10-21'

นี่เป็นวิธีที่มีประสิทธิภาพมากที่สุด, หน่วยความจำต่ำสุด, วิธีการใช้ทรัพยากรน้อยที่สุดและรองรับคุณสมบัติ MySQL ทั้งหมดและมุมตัวพิมพ์เช่นความแม่นยำของการประทับเวลาย่อยที่สอง นอกจากนี้ยังเป็นข้อพิสูจน์ในอนาคต


1
และด้วยการใช้เหตุผลด้านประสิทธิภาพของคุณ "> =" และ "<" จะถูกคำนวณอย่างเท่าเทียมกันในแต่ละแถวของตารางหรือเซิร์ฟเวอร์ SQL เพียงแค่ "น่าอัศจรรย์" จะรู้ได้อย่างไรว่ามีจำนวนมากกว่าหรือไม่? :-)
Javier Guerrero

@JavierGuerrero: ตัวอย่างของฉันเปรียบเทียบค่าคงที่สองรายการ: หนึ่งค่าจากตารางและสตริงตัวอักษร
dotancohen

"หนึ่งจากตาราง" ไม่คงที่มันแตกต่างกันไปในแต่ละแถวดังนั้นการคำนวณเดียวกันจะต้องทำในแต่ละแถว (และทั้งคู่จะต้องถูกแปลงเป็นเวลายุคเพื่อทำการเปรียบเทียบ)
Javier Guerrero

9

นี่คือรูปแบบทั้งหมด

พูดนี้เป็นคอลัมน์ที่มีค่าโต๊ะdatetimedata

+--------------------+
| date_created       |
+--------------------+
| 2018-06-02 15:50:30|
+--------------------+

mysql> select DATE(date_created) from data;
+--------------------+
| DATE(date_created) |
+--------------------+
| 2018-06-02         |
+--------------------+

mysql> select YEAR(date_created) from data;
+--------------------+
| YEAR(date_created) |
+--------------------+
|               2018 |
+--------------------+

mysql> select MONTH(date_created) from data;
+---------------------+
| MONTH(date_created) |
+---------------------+
|                   6 |
+---------------------+

mysql> select DAY(date_created) from data;
+-------------------+
| DAY(date_created) |
+-------------------+
|                 2 |
+-------------------+

mysql> select HOUR(date_created) from data;
+--------------------+
| HOUR(date_created) |
+--------------------+
|                 15 |
+--------------------+

mysql> select MINUTE(date_created) from data;
+----------------------+
| MINUTE(date_created) |
+----------------------+
|                   50 |
+----------------------+

mysql> select SECOND(date_created) from data;
+----------------------+
| SECOND(date_created) |
+----------------------+
|                   31 |
+----------------------+

5

คุณสามารถใช้ได้:

DATEDIFF ( day , startdate , enddate ) = 0

หรือ:

DATEPART( day, startdate ) = DATEPART(day, enddate)
AND 
DATEPART( month, startdate ) = DATEPART(month, enddate)
AND
DATEPART( year, startdate ) = DATEPART(year, enddate)

หรือ:

CONVERT(DATETIME,CONVERT(VARCHAR(12), startdate, 105)) = CONVERT(DATETIME,CONVERT(VARCHAR(12), enddate, 105))

5

วิธีที่ง่ายและดีที่สุดในการใช้ฟังก์ชั่นวันที่

ตัวอย่าง

SELECT * FROM 
data 
WHERE date(datetime) = '2009-10-20' 

หรือ

SELECT * FROM 
data 
WHERE date(datetime ) >=   '2009-10-20'  && date(datetime )  <= '2009-10-20'

-5

การใช้LIKEคำสั่ง in เป็นตัวเลือกที่ดีที่สุดที่ WHERE datetime LIKE '2009-10-20%' ควรใช้ในกรณีนี้

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