Kueri postgresql antara rentang tanggal

126

Saya mencoba untuk menanyakan postgresql db saya untuk mengembalikan hasil di mana tanggal dalam bulan dan tahun tertentu. Dengan kata lain, saya ingin semua nilai untuk satu bulan-tahun.

Satu-satunya cara saya bisa melakukannya sejauh ini adalah seperti ini:

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

Masalahnya adalah saya harus menghitung tanggal pertama dan tanggal terakhir sebelum menanyakan tabel. Apakah ada cara yang lebih sederhana untuk melakukan ini?

Terima kasih

John
sumber
Apakah intervalnya selalu sebulan atau mungkinkah, Anda mulai mungkin pada tanggal 15 dan berakhir pada tanggal 7 bulan berikutnya?
frlan

Jawaban:

202

Dengan tanggal (dan waktu) banyak hal menjadi lebih sederhana jika Anda gunakan >= start AND < end.

Sebagai contoh:

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

Dalam hal ini, Anda masih perlu menghitung tanggal mulai bulan yang Anda butuhkan, tetapi itu harus jelas dalam berbagai cara.

Tanggal akhir juga disederhanakan; cukup tambahkan tepat satu bulan. Jangan main-main dengan 28, 30, 31, dll.


Struktur ini juga memiliki keunggulan karena dapat mempertahankan penggunaan indeks.


Banyak orang mungkin menyarankan formulir seperti berikut ini, tetapi mereka tidak menggunakan indeks:

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

Ini melibatkan penghitungan kondisi untuk setiap baris dalam tabel (pemindaian) dan tidak menggunakan indeks untuk menemukan rentang baris yang akan cocok (pencarian rentang).

MatBailie
sumber
1
Pendekatan pertama perlu dipusingkan dengan bulan (bukan hari) f.ex. 2014-12-01& 2015-01-01. Yang kedua bisa diindeks juga, tapi itu tidak sepele, saya akui - EXTRACT()sepertinya lebih cocok.
pozs
1
Anda dapat menghindari perhitungan tanggal dalam aplikasi Anda dengan menggunakan interval. misalnya: WHERE login_date> = '2014-02-01' AND login_date <'2014-02-01' :: date + INTERVAL '1 month' Ini masih menggunakan indeks sambil menyederhanakan kode Anda.
baswell
53

Dari PostreSQL 9.2 Jenis Rentang didukung. Jadi Anda bisa menulis ini seperti:

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

ini harus lebih efisien daripada perbandingan string

Ana María Martínez Gómez
sumber
23

Untuk berjaga-jaga jika seseorang mendarat di sini ... sejak 8.1 Anda dapat menggunakan:

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

Dari dokumen:

ANTARA SIMETRIK sama dengan ANTARA kecuali tidak ada persyaratan bahwa argumen di sebelah kiri AND harus kurang dari atau sama dengan argumen di sebelah kanan. Jika tidak, kedua argumen tersebut secara otomatis ditukar, sehingga rentang tidak kosong selalu tersirat.

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

Antara kata kunci bekerja sangat baik untuk kencan. itu mengasumsikan waktu pada 00:00:00 (yaitu tengah malam) untuk tanggal.

Chaudhary Sarimurrab
sumber
-14

Bacalah dokumentasinya.

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

Saya menggunakan kueri seperti itu:

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

atau

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

Juanitos Ingenier.

Juan Garfias
sumber
2
Ini tidak menjawab pertanyaan dengan tepat. Pertanyaannya menanyakan tanggal berdasarkan bulan dan tahun.
Ram