2015-05-01 1 views
0

У меня есть этот Peewee запрос:Неправильный результат в SQL. Подзапрос срывается, но почему?

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, потому что, когда я запускаю вышеуказанный SQL в консоли Postgres, он также возвращает тот же неправильный набор данных.

UPDATE @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 

Мысли?

+0

Я пробовал другой подход, используя предложения HAVING, сообщите мне, если он близко. – coleifer

+0

Любая обратная связь? Мы на правильном пути? – coleifer

+0

lol bro cole? Cole ??? – coleifer

ответ

-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 
+0

«Не имеет смысла делать счет (t.id) и группу по t.id в то же время». --- оно делает. Он идентичен 'COUNT (*)' в этом случае (который должен был использоваться вместо этого фактически) – zerkms

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')) 
+0

Coleifer, записывая запрос, является трудной частью. Если бы у меня было это, я думаю, что мог бы придумать запрос Peewee. :( – commadelimited