2014-02-18 3 views
0

Я использую Postgres 9.1, чтобы попробовать и получить некоторые данные.
У меня есть три (фиктивных/продезинфицировать) таблицы:Запрос с использованием счетчиков с несколькими условиями

Table "public.students" 
    Column |   Type    | Modifiers 
--------------+-----------------------------+----------- 
id   | uuid      | not null 
name   | character varying   | 
birth_date | date      | 
last_exam_at | timestamp without time zone | 
created_at | timestamp without time zone | 
code   | character varying   | 
gender  | character varying   | 
Indexes: 
    "students_id_key" UNIQUE CONSTRAINT, btree (id) 
Referenced by: 
    TABLE "exams" CONSTRAINT "exams_student_id_fkey" 
        FOREIGN KEY (student_id) REFERENCES students(id) 

Table "public.exams_essays" 
    Column | Type | Modifiers 
----------+------+----------- 
exam_id | uuid | 
essay_id | uuid | 

Table "public.exams" 
     Column  |   Type    | Modifiers 
-------------------+-----------------------------+----------- 
id    | uuid      | not null 
student_id  | uuid      | 
created_at  | timestamp without time zone | 
completed_at  | timestamp without time zone | 
course   | character varying   | 

Table "public.essays" 
    Column  |   Type    | Modifiers 
-----------------+-----------------------------+----------- 
id    | uuid      | not null 
essay_type  | character varying   | not null 
filename  | character varying   | 

И я пытаюсь получить следующую информацию, сгруппированных по created_at::date и student_id:

  • общее количество экзаменов
  • номер (exam.course = 'history')
  • количество английских эссе (exam.course = 'english')

Каждый из этих запросов не является слишком сложным для индивидуального использования, но их объединение затруднено.

ответ

1
SELECT created_at::date, student_id 
     ,count(*) AS exams 
     ,sum(CASE WHEN course = 'history' THEN essays ELSE 0 END) AS essays_hist 
     ,sum(CASE WHEN course = 'english' THEN essays ELSE 0 END) AS essays_engl 
FROM public.exams x 
LEFT JOIN (
    SELECT exam_id AS id, count(*) AS essays 
    FROM public.exams_essays 
    GROUP BY exam_id 
    ) s USING (id) 
GROUP BY created_at::date, student_id; 

я агрегировать н-таблицу перед тем на соединение, что позволяет избежать умножения строк, чтобы начать с. Делает запрос немного проще (IMO) и быстрее.

+0

@David: Вы знаете, что 'GROUP BY 1' является допустимым синтаксисом, верно? [Пример.] (Http://stackoverflow.com/questions/3800551/select-first-row-in-each-group-by-group/7630564#7630564) –

+0

Да, я (сейчас) знаю об этом, но Я должен был найти его, и я нашел запрос более ясным, более поддающимся игре и менее хрупким, со всем изложенным. –

1
SELECT COUNT(DISTINCT EX.exam_id) TotalExams, 
     SUM(CASE WHEN E.course = 'history' THEN 1 ELSE 0 END) HistoryEssays, 
     SUM(CASE WHEN E.course = 'english' THEN 1 ELSE 0 END) EnglishEssays 
FROM public.exams AS EX 
LEFT JOIN public.exams_essays AS EE 
    ON EX.exam_id = EE.essay_id 
+0

Мне нужно количество эссе, хотя это может отличаться от экзамена, поскольку один экзамен может иметь много эссе. –

+1

@ DavidN.Welton О, ладно, не понял этого. Обновлен мой ответ. – Lamak

Смежные вопросы