Как группировать по столбцу из подзапроса - PullRequest
0 голосов
/ 12 сентября 2018

У меня есть таблица задач с

tasks_id | start_time_id | end_time_id | start_date | end_date

t1       | st_1          | et_1        | 20180903   | 20180903
t2       | st_2          | et_2        | 20180903   | 20180903
t3       | st_3          | et_3        | 20180903   | 20180903
t4       | st_4          | et_4        | 20180903   | 20180903
t5       | st_5          | et_5        | 20180903   | 20180903
t6       | st_6          | et_6        | 20180903   | 20180904

start_time и end_time - это идентификаторы, которые объединяются с time_table для получения военных часов, таких как

   time_id   | military_hour 
   st1       | 0
   st2       | 2
   st3       | 7
   st4       | 16
   st5       | 18
   st6       | 23
   et1       | 0
   et2       | 2
   et3       | 8
   et4       | 16
   et5       | 18
   et6       | 0  

Я могу присоединиться к таблице tasks с time_table дважды , если я хочу знать военные часы как start_time_id, так и end_time_id.

SELECT        t1.tasks_id as task_inst_id,
              t1.start_time_id,
              t1.end_time_id,
              t1.end_date as end_date,
              t1.start_date as start_date
      FROM task_instances t1
      INNER JOIN time_table td1 
              ON t1.start_time_id = td1.time_id
      INNER JOIN time_table td2 
              ON t1.end_time_id = td2.time_id 

Я могу разделить военные часы в окнах по 4 часа каждое, так что за день есть 6 окон или групп военных часов как

  (FLOOR(military_hour / 4)) AS military_hour_group

Я хочу знать no of all the tasks that either started or ended in those windows if I pass a particular day.

Я пытался

SELECT
tq1.start_military_hour_group,
tq1.end_date,
COUNT(tq1.task_inst_id) as no_of_tasks
FROM
(
SELECT        t1.tasks_id as task_inst_id,
              t1.start_time_id,
              t1.end_time_id,
              t1.end_date as end_date,
              (FLOOR(td1.military_hour / 4)*4) AS start_military_hour_group,
              (FLOOR(td2.military_hour / 4)*4) AS end_military_hour_group
      FROM task_instances t1
      INNER JOIN time_table td1 
              ON t1.start_time_id = td1.time_id
      INNER JOIN time_table td2 
              ON t1.end_time_id = td2.time_id 

      /* I don't know how to put the where condition */

      WHERE t1.end_date = '20180903':: int 
)tq1
GROUP BY tq1.start_military_hour_group,tq1.end_date
ORDER BY tq1.end_date,tq1.start_military_hour_group;

Я знаю, что что-то упустил, но что именно?

Я присоединяюсь дважды, поэтому я предполагаю, что он создает 2 строки для одной и той же строки из таблицы задач, и мне следует взять end_date или start_date?

Пожалуйста, объясните.

например. Для набора образцов

0 - 3 group - 2 tasks
4-7 group - 1 task
8-11 group - 0 
12-15 group - 0
16 - 19 group - 2 taks
20-23 group - 1 task

Ответы [ 2 ]

0 голосов
/ 12 сентября 2018

Первым делом первым делом. Вы должны переосмыслить свою модель данных - start_time_id и end_time_id, и отдельная таблица с избыточными данными (time_table) не является хорошим дизайном. Вы можете иметь часы как start_time и end_time.

Теперь давайте разрешим вашу проблему с вашим реальным дизайном.

with time_groups as (select * from (values (0, '0 - 3 group'),
                                           (1, '4 - 7 group'),
                                           (2, '8 - 11 group'),
                                           (3, '12 - 15 group'),
                                           (4, '16 - 19 group'),
                                           (5, '20 - 23 group')) a (id, name))

select tg.name, coalesce(tasks,0) tasks
  from (select tt1.military_hour/4 time_group_id, count(*)  tasks
          from task_instances ti
          LEFT join time_table tt1 on ti.start_time_id=tt1.time_id
          LEFT JOIN time_table tt2 on ti.end_time_id=tt2.time_id
         where ti.end_date='20180903' or ti.end_date is null
         group by tt1.military_hour/4
         order by 1) a
  right join time_groups tg on a.time_group_id=tg.id
0 голосов
/ 12 сентября 2018

Я бы пошел по другому пути.Этот код проще, хотя, вероятно, менее эффективен, чем объединение дважды.

select  count(distinct ti.tasks_id), floor(td.military_hour/4)*4 time_group
from time_dimension td
join time_instance ti on td.time_id in (ti.start_time_id, ti.end_time_id)
group by  floor(td.military_hour/4)*4 time_group
where td.end_date = '2018090'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...