Django возвращает неправильные результаты при выборе из представления postgres

У меня есть представление, определенное в postgres, в отдельной схеме для данных, которые оно использует. Он содержит три столбца:

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

Когда я запрашиваю его из psql или администратора, я получаю такие результаты:

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;

а "another_view" выглядит так:

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

(некоторые столбцы опущены)


person maniexx    schedule 21.09.2015    source источник
comment
Что такое "betbot_views"."daily_results" и почему вы используете его в своем коде вместо "my_views"."results"? Можете ли вы показать свое определение представления (код SQL для его воссоздания)?   -  person GwynBleidD    schedule 21.09.2015
comment
Также будет полезно, если вы можете показать пример из исходной таблицы (таблиц) для вашего представления.   -  person GwynBleidD    schedule 21.09.2015
comment
@GwynBleidD имена были просто результатом того, что я забыл их последовательно редактировать, теперь это исправлено. Что касается определения представления, то это довольно сложное представление, зависящее от других представлений и множества данных. Я надеялся, что это не имеет значения. Одно могу сказать, что эти данные не меняются от звонка к звонку, так как я проверял это с точными результатами несколько раз, в течение двух дней.   -  person maniexx    schedule 21.09.2015
comment
Есть одно возможное решение, но чтобы подтвердить, что я должен знать, какой тип полей находится в исходных данных и как вычисляются поля из представления. Дело не в кеше, а в типах данных и изменениях окружения.   -  person GwynBleidD    schedule 21.09.2015
comment
@GwynBleidD Добавил определение к вопросу.   -  person maniexx    schedule 21.09.2015


Ответы (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;

Таким образом, дни всегда будут считаться в соответствии с часовым поясом UTC.

person GwynBleidD    schedule 21.09.2015