Django中的SQL查询产生不同的结果

时间:2019-03-04 15:55:39

标签: python sql django postgresql count

我正在使用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))

2 个答案:

答案 0 :(得分:2)

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

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

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

答案 1 :(得分:0)

在没有看到数据的情况下,很难确定差异。

一种可能性:您有一个复杂的联接条件,其中有些似乎更适合于限制(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'
-- …