sql >> Databasteknik >  >> RDS >> PostgreSQL

Rails/Postgresql SQL-skillnader med datum

Versionen av generate_series som du använder arbetar med tidsstämplar, inte datum. Så din '2012-10-14' och current_date konverteras till timestamp with time zone s och generate_series producerar en uppsättning timestamp with time zone s; jämför dessa:

=> 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)

Den första har tidszoner, den andra inte.

Men, current_date konverteras alltid till en tidsstämpel med databassessionens tidszonsjustering tillämpad. Rails-sessionen kommer att prata med databasen i UTC, din psql session använder förmodligen ET.

Om du manuellt anger aktuellt datum och uttryckligen arbetar med timestamp s:

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

då får du samma sju resultat i båda eftersom det inte finns någon tidszon i sikte för att göra en enda röra.

Det enklaste sättet att ignorera tidszoner är att använda heltalsversionen av generate_series och det faktum att lägga till ett heltal till ett datum behandlar heltal som ett antal dagar:

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

Det ger dig samma sju dagar utan tidszonstörningar. Du kan fortfarande använda current_date (som inte har någon tidszon eftersom SQL-datum inte har tidszoner) genom att notera att skillnaden mellan två datum är antalet dagar mellan dem (ett heltal):

=> 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)

och från 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"}]

BTW, jag hatar tidszoner, hatar och föraktar dem.




  1. Hur man uppdaterar/tar bort med element från två olika tabeller SQLite

  2. Fler av mina favoritpostgreSQL-frågor - och varför de också är viktiga

  3. Hur man använder IDENTITY()-funktionen i SQL Server

  4. Information om informationsschemadatabasen i MySQL