【问题标题】:SQL Query in Django yielding different resultDjango中的SQL查询产生不同的结果
【发布时间】:2019-03-04 15:55:38
【问题描述】:

我正在使用 django.db.connection 在我的 PostgreSQL 数据库和 Django 中运行查询。但由于某种原因,我在 Django 中的查询会产生完全不同的结果。这是我的查询及其相应的结果。

PostgreSQL 中的查询

WITH calendar AS
    ( SELECT d
    FROM generate_series(date_trunc('day', CURRENT_DATE - INTERVAL '6 day'), CURRENT_DATE, '1 day'::interval) d)
    SELECT n.device_name AS dev_name,
        c.d::date AS dev_date,
        COUNT(mc.id)
    FROM
    (SELECT DISTINCT device_name
    FROM machine_counter) n
    CROSS JOIN calendar c
    LEFT JOIN machine_counter mc ON mc.device_datetime >= c.d + INTERVAL '7 hour'
    AND mc.device_datetime < c.d + INTERVAL '1 day 7 hour'
    AND n.device_name = mc.device_name
    GROUP BY n.device_name,
            c.d
    ORDER BY c.d,
            n.device_name;

views.py

def getMachineCount(request):
    cursor = connection.cursor()
    cursor.execute(
    '''
    WITH calendar AS
    ( SELECT d
    FROM generate_series(date_trunc('day', CURRENT_DATE - INTERVAL '6 day'), CURRENT_DATE, '1 day'::interval) d)
    SELECT n.device_name AS dev_name,
        c.d::date AS dev_date,
        COUNT(mc.id)
    FROM
    (SELECT DISTINCT device_name
    FROM machine_counter) n
    CROSS JOIN calendar c
    LEFT JOIN machine_counter mc ON mc.device_datetime >= c.d + INTERVAL '7 hour'
    AND mc.device_datetime < c.d + INTERVAL '1 day 7 hour'
    AND n.device_name = mc.device_name
    GROUP BY n.device_name,
            c.d
    ORDER BY c.d,
            n.device_name;
    '''
    )
    records = cursor.fetchall()
    col_list = [desc[0] for desc in cursor.description]

    print(records)

    result = bindQueryColumnDescription(records, col_list)

    return HttpResponse(json.dumps(result, default=dateConverter))

【问题讨论】:

  • 在数据库服务器上记录查询,看看您是否真的在运行相同的两个查询。看起来您可能没有连接到同一个实例。通过比较来自控制台和 Django 的select CURRENT_DATE;,我会简化/排除一些事情。

标签: python sql django postgresql count


【解决方案1】:

如果两个数据库客户端使用不同的时区,则日期时间文字(例如“2019-02-26 07:00:00”)将在每个客户端中指定不同的值。

您可以更改文字以包含明确的时区,例如“2019-02-26 07:00:00 UTC”,这将避免使用客户端的时区。

在任何客户端中执行此操作,每个客户端将始终为该字面量使用相同的值。

【讨论】:

  • 当我在我的个人查询中包含一个明确的时区时,计数匹配。但是我将如何在 Django 方面解决这个问题?我已将 settings.py 中的 TIME_ZONE 更改为我的本地时区。
  • “但是我该如何在 Django 这边解决这个问题呢?” — 在任何客户端中,您都可以通过始终在用于查询的任何日期时间文字中指定时区来避免其时区。
  • 谢谢!我能够使用AT TIME ZONE 'EST' 使其工作
【解决方案2】:

没有看到数据,很难确定差异。

一种可能性:您有一个复杂的连接条件,其中一些似乎更适合限制(WHERE 条件)。

我建议你改变:

-- …
    LEFT JOIN machine_counter AS mc
         ON mc.device_datetime >= c.d + INTERVAL '7 hour'
             AND mc.device_datetime < c.d + INTERVAL '1 day 7 hour'
             AND n.device_name = mc.device_name
-- …

改为:

-- …
    LEFT JOIN machine_counter AS mc
         ON n.device_name = mc.device_name
-- …
WHERE
    mc.device_datetime >= c.d + INTERVAL '7 hour'
    AND mc.device_datetime < c.d + INTERVAL '1 day 7 hour'
-- … 

【讨论】:

  • 这真的很奇怪。即使我明确地尝试查询一天的计数,它仍然是不同的结果。 SELECT COUNT(id) FROM machine_counter WHERE device_datetime &gt;= '2019-02-26 07:00:00' AND device_datetime &lt; '2019-02-27 07:00:00' AND device_name = 'line1' 此查询通过 Django 生成 9248,在 PostgreSQL 中生成 9153
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-29
  • 2019-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多