从postgres视图中选择时,Django返回错误的结果

时间:2015-09-21 13:48:27

标签: sql django postgresql sql-view

我在postgres中定义了一个视图,在一个单独的模式中定义了它正在使用的数据。 它包含三列:

mydb=# \d "my_views"."results"
View "my_views.results"
  Column   |         Type          | Modifiers 
-----------+-----------------------+-----------
 Date      | date                  | 
 Something | character varying(60) | 
 Result    | numeric               | 

当我从psql或adminer查询它时,我得到的结果就像theese:

bb_adminpanel=# select * from "my_views"."results";
    Date    |          Something          |    Result    
------------+-----------------------------+--------------
 2015-09-14 | Foo                         |  -3.36000000
 2015-09-14 | Bar                         | -16.34000000
 2015-09-12 | Foo                         | -11.55000000
 2015-09-12 | Bar                         |  11.76000000
 2015-09-11 | Bar                         |   2.48000000

然而,通过django查询它,我得到一个不同的集合: (c是数据库上的游标对象)

c.execute('SELECT * from "my_views"."results"')
c.fetchall()
[(datetime.date(2015, 9, 14), 'foo', Decimal('-3.36000000')),
 (datetime.date(2015, 9, 14), 'bar', Decimal('-16.34000000')),
 (datetime.date(2015, 9, 11), 'foo', Decimal('-11.55000000')),
 (datetime.date(2015, 9, 11), 'bar', Decimal('14.24000000'))]

根本不匹配 - 前两行是正确的,但最后两行非常奇怪 - 它们有一个转移的日期,最后一条记录的结果是最后两行的总和。

我不知道为什么会这样,欢迎任何建议。

<小时/> 以下是视图定义:

 SELECT a."Timestamp"::date AS "Date",
    a."Something",
    sum(a."x") AS "Result"
   FROM my_views.another_view a
  WHERE a.status::text = ANY (ARRAY['DONE'::character varying::text, 'CLOSED'::character varying::text])
  GROUP BY a."Timestamp"::date, a."Something"
  ORDER BY a."Timestamp"::date DESC;

和&#34; another_view&#34;看起来像这样:

          Column           |           Type           | Modifiers 
---------------------------+--------------------------+-----------
 Timestamp                 | timestamp with time zone |  
 Something                 | character varying(60)    | 
 x                         | numeric                  | 
 status                    | character varying(100)   | 

(某些列无名)

1 个答案:

答案 0 :(得分:1)

问题的简单解释是:时区。

详细说明:连接到PostgreSQL控制台时,您没有声明任何时区设置,但django会在每个查询中执行此操作。这样,某些记录的时间戳将根据使用的时区指向不同的日期,例如使用数据

+-------------------------+-----------+-------+--------+
|        timestamp        | something |   x   | status |
+-------------------------+-----------+-------+--------+
| 2015-09-11 12:00:00 UTC | foo       |  2.48 | DONE   |
| 2015-09-12 00:50:00 UTC | foo       | 11.76 | DONE   |
+-------------------------+-----------+-------+--------+

查询使用时区UTC执行的视图将为您提供2行,但使用时区GMT-2执行的查询将只提供一行。因为在GMT-2时区timestamp来自第二排仍然是2015-09-11。

要解决此问题,您可以修改视图,因此它会始终根据指定的时区对日期进行分组:

 SELECT (a."Timestamp" AT TIME ZONE 'UTC')::date AS "Date",
    a."Something",
    sum(a."x") AS "Result"
   FROM my_views.another_view a
  WHERE a.status::text = ANY (ARRAY['DONE'::character varying::text, 'CLOSED'::character varying::text])
  GROUP BY (a."Timestamp" AT TIME ZONE 'UTC'), a."Something"
  ORDER BY (a."Timestamp" AT TIME ZONE 'UTC') DESC;

这样的日子总是按照&#39; UTC&#39;来计算。时区。