sql >> Databáze >  >> RDS >> PostgreSQL

Rails/Postgresql rozdíly SQL s daty

Verze generate_series který používáte, pracuje s časovými razítky, nikoli s daty. Takže vaše '2012-10-14' a current_date se převádějí na timestamp with time zone s a generate_series vytváří sadu timestamp with time zone s; porovnejte tyto:

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

První má časová pásma, druhá ne.

Ale current_date vždy se převede na časové razítko s použitím úpravy časového pásma relace databáze. Relace Rails bude mluvit s databází v UTC, vaše psql relace pravděpodobně používá ET.

Pokud ručně zadáte aktuální datum a budete explicitně pracovat s timestamp s:

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

pak získáte stejných sedm výsledků v obou, protože v dohledu není žádné časové pásmo, které by ve věcech dělalo nepořádek.

Nejjednodušší způsob, jak ignorovat časová pásma, je použít celočíselnou verzi generate_series a skutečnost, že přidání celého čísla k datu považuje celé číslo za počet dní:

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

To vám dá stejných sedm dní bez rušení časového pásma. Stále můžete použít current_date (který nemá žádné časové pásmo, protože data SQL nemají časová pásma) tím, že rozdíl mezi dvěma daty je počet dní mezi nimi (celé číslo):

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

a z 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, nesnáším časová pásma, nenávidím je a pohrdám jimi.




  1. Je lepší použít kurzorový adaptér nebo adaptér pole

  2. Použijte proměnnou nastavenou meta-příkazem psql uvnitř bloku DO

  3. Aktualizujte záznamy v tabulce z CTE

  4. Aktualizujte více tabulek v SQL Server pomocí INNER JOIN