SQL中的结果不正确。子查询被塞了,但为什么呢?

时间:2015-05-01 02:27:02

标签: postgresql peewee

我有这个Peewee查询:

stats = (
    Assignment.select(
        Type.name,
        fn.COUNT(Type.id).alias('total'),
        Assignment.select(
            fn.COUNT(Assignment.id)
        ).where(
            (Assignment.due_date < fn.Now()) & (StudentCourses.student == self) & (Assignment.type == Type.id)
        ).group_by(Assignment.type, StudentCourses.student).alias('completed')
    )
    .naive().join(Type)
    .join(StudentCourses, on=(StudentCourses.course == Assignment.course))
    .where(StudentCourses.student == self)
    .order_by(Type.id)
    .group_by(Type.id, Type.name, StudentCourses.student)
)

导致以下SQL

SELECT t.NAME
    ,COUNT(t.id) AS total
    ,(
        SELECT COUNT(ass.id)
        FROM assignment AS ass
        WHERE (
                (
                    (ass.due_date < Now())
                    AND (sc.student_id = 61)
                    )
                AND (ass.type_id = t.id)
                )
        GROUP BY ass.type_id,sc.student_id
        ) AS completed
FROM assignment AS a
INNER JOIN type AS t ON (a.type_id = t.id)
INNER JOIN studentcourses AS sc ON (sc.course_id = a.course_id)
WHERE (sc.student_id = 61)
GROUP BY t.id
    ,t.NAME
    ,sc.student_id
ORDER BY t.id

返回此数据集:

   name   | total | completed
----------+-------+-----------
 Homework |    18 |        88
 Test     |     7 |        20
 Final    |     2 |
 Custom   |    29 |        85
 In Class |    18 |        49
(5 rows)

问题是完成的部分是错误的。它应该是这样的:

   name   | total | completed
----------+-------+-----------
 Homework |    18 |        16
 Test     |     7 |        5
 Final    |     2 |        0
 Custom   |    29 |        24
 In Class |    18 |        9

有人可以帮助他们弄清楚这里出了什么问题吗?我不认为这是一个Peewee问题,因为当我在Postgres控制台中运行上述SQL时,它也会返回相同的错误数据集。

更新 @coleifer,我尝试了你的建议,结果产生了以下SQL:

SELECT "t1"."name",
  (SELECT COUNT("t2"."id")
   FROM "assignment" AS t2
   INNER JOIN "studentcourses" AS t3 ON ("t3"."course_id" = "t2"."course_id")
   WHERE (("t3"."student_id" = 61)
          AND ("t2"."type_id" = "t1"."id"))
   GROUP BY "t2"."type_id") AS total,
  (SELECT COUNT("t2"."id")
   FROM "assignment" AS t2
   INNER JOIN "studentcourses" AS t3 ON ("t3"."course_id" = "t2"."course_id")
   WHERE (("t3"."student_id" = 61)
          AND ("t2"."type_id" = "t1"."id"))
   GROUP BY "t2"."type_id" HAVING ("t2"."due_date" < NOW())) AS completed
FROM "type" AS t1

遗憾的是,这个错误发生了错误:

ERROR:  column "t2.due_date" must appear in the GROUP BY clause or be used in an aggregate function
LINE 13:    GROUP BY "t2"."type_id" HAVING ("t2"."due_date" < NOW()))...

我尝试将t2.due_date放入群组中并收到另一个错误:

ERROR:  more than one row returned by a subquery used as an expression

思想?

2 个答案:

答案 0 :(得分:0)

如果您知道产生所需结果的SQL查询,我很乐意帮助您将其翻译成“peewee”。你能编写一个查询,为你提供你想要的结果吗?

试图解开你在这里得到的东西......

我认为您在StudentCourse上的外部联接存在问题,但对子查询计数分配没有预期的影响。我会尝试不同的方法,也许它会起作用?

# I have no idea if this will actually work.
total = (Assignment
         .select(fn.COUNT(Assignment.id))
         .join(
             StudentCourses, on=(
                 StudentCourses.course == Assignment.course))
         .where(
             (StudentCourses.student == self) &
             (Assignment.type == Type.id))
         .group_by(Assignment.type))

# Maybe HAVING will work?
completed = total.having(Assignment.due_date < fn.NOW())

# This query just selects types
stats = Type.select(
    Type.name,
    total.alias('total'),
    completed.alias('completed'))

答案 1 :(得分:-1)

我不确定我理解您的查询。

  • 子查询中的where子句似乎有一些不必要的括号
  • 我不懂student_id的小组,因为你已经有了student_id = 61的地方
  • 同时按t.id执行计数(t.id)和组是没有意义的。
  • 我不理解主查询中的ORDER BY t.id

如果我理解你要做什么,我会这样做:

select t.name, count(t.id), count(case when a.due_date < Now() then 1 else null end) 
from type t, studentcourses s, assignment a 
where a.course_id = sc.course_id and a.type_id = t.id and sc.student_id = 61 
group by t.name