Tarih aralıkları arasında Postgresql sorgusu


127

Postgresql db'mi, bir tarihin belirli ay ve yılda olduğu sonuçları döndürmek için sorgulamaya çalışıyorum. Diğer bir deyişle, bir aylık-yıllık tüm değerleri istiyorum.

Şimdiye kadar bunu yapabilmemin tek yolu şuydu:

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

Bununla ilgili sorun, tabloyu sorgulamadan önce ilk tarihi ve son tarihi hesaplamam gerekmesidir. Bunu yapmanın daha basit bir yolu var mı?

Teşekkürler


Aralık her zaman bir ay mıdır yoksa 15'inde başlayıp sonraki ayın 7'sinde bitmeniz olabilir mi?
frlan

Yanıtlar:


202

Tarihlerle (ve saatlerle), kullanırsanız birçok şey daha basit hale gelir >= start AND < end.

Örneğin:

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

Bu durumda, ihtiyaç duyduğunuz ayın başlangıç ​​tarihini yine de hesaplamanız gerekir, ancak bu, herhangi bir şekilde basit olmalıdır.

Bitiş tarihi de basitleştirilmiştir; sadece bir ay ekleyin. 28., 30., 31. vb. İle uğraşmak yok.


Bu yapı aynı zamanda dizinlerin kullanımını sürdürme avantajına da sahiptir.


Birçok kişi Aşağıdaki gibi bir form önerebilir, ancak bunlar yok dizinleri kullanın:

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

Bu, tablodaki her bir satır için koşulların hesaplanmasını (bir tarama) ve eşleşecek satırların aralığını bulmak için dizini kullanmamayı (aralık arama) içerir.


1
İlk yaklaşımın aylarla (günler yerine) uğraşması gerekiyor f.ex. 2014-12-01& 2015-01-01. İkincisi de dizine eklenebilir, ancak bu önemsiz değil, kabul ediyorum - EXTRACT()daha uyumlu görünüyor.
Pozs

1
Interval kullanarak uygulamanızda tarih hesaplamalarının önüne geçebilirsiniz. örneğin: WHERE login_date> = '2014-02-01' AND login_date <'2014-02-01' :: date + INTERVAL '1 month' Bu kodunuzu basitleştirirken yine de indeksleri kullanır.
baswell

53

PostreSQL 9.2'den Aralık Türleri desteklenir. Yani bunu şöyle yazabilirsiniz:

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

bu, dize karşılaştırmasından daha verimli olmalıdır


23

Birinin buraya inmesi ihtimaline karşı ... 8.1'den beri basitçe şunları kullanabilirsiniz:

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

Dokümanlardan:

BETWEEN SYMMETRIC, BETWEEN ile aynıdır, ancak AND'nin solundaki argümanın sağdaki argümandan küçük veya ona eşit olmasına gerek yoktur. Değilse, bu iki bağımsız değişken otomatik olarak değiştirilir, böylece boş olmayan bir aralık her zaman ima edilir.


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

Between keyword bir tarih için istisnai olarak çalışır. tarihler için saatin 00:00:00 (yani gece yarısı) olduğunu varsayar.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.