แบบสอบถาม Postgresql ระหว่างช่วงวันที่


127

ฉันพยายามสอบถามฐานข้อมูล postgresql ของฉันเพื่อส่งคืนผลลัพธ์ที่วันที่อยู่ในเดือนและปีที่แน่นอน กล่าวอีกนัยหนึ่งฉันต้องการค่าทั้งหมดสำหรับเดือนต่อปี

วิธีเดียวที่ฉันทำได้จนถึงตอนนี้คือ:

SELECT user_id 
FROM user_logs 
WHERE login_date BETWEEN '2014-02-01' AND '2014-02-28'

ปัญหาคือฉันต้องคำนวณวันที่แรกและวันที่สุดท้ายก่อนที่จะค้นหาตาราง มีวิธีที่ง่ายกว่านี้ไหม

ขอบคุณ


ช่วงเวลาเป็นเดือนเสมอหรืออาจเป็นได้ว่าคุณอาจเริ่มที่ 15 และสิ้นสุดในวันที่ 7 ของเดือนถัดไป?
ศุกร์

คำตอบ:


202

กับวันที่ (และครั้ง) >= start AND < endหลายสิ่งหลายอย่างกลายเป็นง่ายถ้าคุณใช้

ตัวอย่างเช่น:

SELECT
  user_id
FROM
  user_logs
WHERE
      login_date >= '2014-02-01'
  AND login_date <  '2014-03-01'

ในกรณีนี้คุณยังคงต้องคำนวณวันที่เริ่มต้นของเดือนที่คุณต้องการ แต่ควรตรงไปตรงมาในหลาย ๆ วิธี

วันที่สิ้นสุดยังทำให้ง่ายขึ้น เพิ่มแค่หนึ่งเดือนเท่านั้น ไม่ยุ่งเกี่ยวกับ 28, 30, 31, ฯลฯ


โครงสร้างนี้ยังมีข้อดีคือสามารถรักษาการใช้ดัชนีได้


หลายคนอาจแนะนำแบบฟอร์มดังต่อไปนี้ แต่ไม่ใช้ดัชนี:

WHERE
      DATEPART('year',  login_date) = 2014
  AND DATEPART('month', login_date) = 2

สิ่งนี้เกี่ยวข้องกับการคำนวณเงื่อนไขสำหรับทุกแถวเดียวในตาราง (การสแกน) และไม่ใช้ดัชนีเพื่อค้นหาช่วงของแถวที่จะตรงกัน (การค้นหาช่วง)


1
แนวทางแรกต้องยุ่งกับเดือน (แทนที่จะเป็นวัน) f.ex. 2014-12-01& 2015-01-01. อันที่สองสามารถจัดทำดัชนีได้เช่นกัน แต่นั่นไม่ใช่เรื่องเล็กน้อยฉันยอมรับ - EXTRACT()ดูเหมือนจะเข้ากันได้มากกว่า
pozs

1
คุณสามารถหลีกเลี่ยงการคำนวณวันที่ในแอปพลิเคชันของคุณได้โดยใช้ช่วงเวลา เช่น WHERE login_date> = '2014-02-01' AND login_date <'2014-02-01' :: date + INTERVAL '1 month' ซึ่งยังคงใช้ดัชนีในขณะที่ทำให้รหัสของคุณง่ายขึ้น
baswell

53

จาก PostreSQL 9.2.2 ประเภทช่วงได้รับการสนับสนุน คุณสามารถเขียนสิ่งนี้ได้ดังนี้:

SELECT user_id
FROM user_logs
WHERE '[2014-02-01, 2014-03-01]'::daterange @> login_date

สิ่งนี้ควรมีประสิทธิภาพมากกว่าการเปรียบเทียบสตริง


23

ในกรณีที่มีคนมาที่นี่ ... ตั้งแต่ 8.1 คุณสามารถใช้:

SELECT user_id 
FROM user_logs 
WHERE login_date BETWEEN SYMMETRIC '2014-02-01' AND '2014-02-28'

จากเอกสาร:

ระหว่าง SYMMETRIC จะเหมือนกับระหว่างนี้ยกเว้นไม่มีข้อกำหนดว่าอาร์กิวเมนต์ทางด้านซ้ายของ AND จะน้อยกว่าหรือเท่ากับอาร์กิวเมนต์ทางด้านขวา หากไม่เป็นเช่นนั้นอาร์กิวเมนต์ทั้งสองนี้จะถูกสลับโดยอัตโนมัติดังนั้นช่วงที่ไม่ว่างจะถูกบอกเป็นนัยเสมอ


-1
SELECT user_id 
FROM user_logs 
WHERE login_date BETWEEN '2014-02-01' AND '2014-03-01'

ระหว่างคำหลักทำงานเป็นพิเศษสำหรับวันที่ จะถือว่าเวลาคือ 00:00:00 น. (เช่นเที่ยงคืน) ของวันที่


-14

อ่านเอกสาร

http://www.postgresql.org/docs/9.1/static/functions-datetime.html

ฉันใช้แบบสอบถามแบบนั้น:

WHERE
(
    date_trunc('day',table1.date_eval) = '2015-02-09'
)

หรือ

WHERE(date_trunc('day',table1.date_eval) >='2015-02-09'AND date_trunc('day',table1.date_eval) <'2015-02-09')    

Juanitos Ingenier


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