PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Rails/Postgresql-SQL-Unterschiede mit Daten

Die Version von generate_series die Sie verwenden, arbeitet mit Zeitstempeln, nicht mit Datumsangaben. Also Ihr '2012-10-14' und current_date werden in timestamp with time zone konvertiert s und generate_series erzeugt eine Reihe von timestamp with time zone s; Vergleichen Sie diese:

=> select generate_series('2012-10-14', current_date, '1 day');
    generate_series     
------------------------
 2012-10-14 00:00:00-07
 2012-10-15 00:00:00-07
 2012-10-16 00:00:00-07
 2012-10-17 00:00:00-07
 2012-10-18 00:00:00-07
 2012-10-19 00:00:00-07
 2012-10-20 00:00:00-07
(7 rows)

=> select generate_series('2012-10-14', current_date::timestamp, '1 day');
   generate_series   
---------------------
 2012-10-14 00:00:00
 2012-10-15 00:00:00
 2012-10-16 00:00:00
 2012-10-17 00:00:00
 2012-10-18 00:00:00
 2012-10-19 00:00:00
 2012-10-20 00:00:00
(7 rows)

Der erste hat Zeitzonen, der zweite nicht.

Aber das current_date wird immer in einen Zeitstempel konvertiert, wobei die Zeitzonenanpassung der Datenbanksitzung angewendet wird. Die Rails-Sitzung kommuniziert mit der Datenbank in UTC, Ihrem psql Die Sitzung verwendet wahrscheinlich ET.

Wenn Sie das aktuelle Datum manuell angeben und explizit mit timestamp arbeiten s:

select generate_series('2012-10-14'::timestamp, '2012-10-20'::timestamp, '1 day')

dann erhalten Sie in beiden die gleichen sieben Ergebnisse, weil keine Zeitzone in Sicht ist, um die Dinge durcheinander zu bringen.

Der einfachste Weg, Zeitzonen zu ignorieren, ist die Verwendung der Integer-Version von generate_series und die Tatsache, dass das Hinzufügen einer Ganzzahl zu einem Datum die Ganzzahl als Anzahl von Tagen behandelt:

select '2012-10-14'::date + generate_series(0, 6)

Das gibt Ihnen die gleichen sieben Tage ohne Zeitzoneninterferenz. Sie können immer noch das current_date verwenden (das keine Zeitzone hat, da SQL-Daten keine Zeitzonen haben), indem Sie beachten, dass die Differenz zwischen zwei Daten die Anzahl der Tage zwischen ihnen ist (eine Ganzzahl):

=> select '2012-10-14'::date + generate_series(0, current_date - '2012-10-14');
  ?column?  
------------
 2012-10-14
 2012-10-15
 2012-10-16
 2012-10-17
 2012-10-18
 2012-10-19
 2012-10-20
(7 rows)

und von Rails:

> pp ActiveRecord::Base.connection.execute("select '2012-10-14'::date + generate_series(0, 6)").to_a
[{"?column?"=>"2012-10-14"},
 {"?column?"=>"2012-10-15"},
 {"?column?"=>"2012-10-16"},
 {"?column?"=>"2012-10-17"},
 {"?column?"=>"2012-10-18"},
 {"?column?"=>"2012-10-19"},
 {"?column?"=>"2012-10-20"}]

Übrigens, ich hasse Zeitzonen, hasse und verachte sie.