2013-12-02 6 views
3

Существует ряд местоположений с членами на разных этапах порядкового процесса. Участники могут быть в нескольких процессах с различным прогрессом в одном или нескольких местах.SQL Query to Count Distinct with Group By with Join

Таблица соединений между местоположениями и членами может выглядеть примерно так: шаги.

| id | member_id | step_no | location_id | process_id | 
------------------------------------------------------- 
| 1 | 1   | 2  | 10   | 57 
| 2 | 1   | 5  | 10   | 58 
| 3 | 2   | 5  | 11   | 37 
| 4 | 2   | 1  | 10   | 57 

Я не был в состоянии понять, как получить количество уникальных членов, по местоположению, по дальнему шагу элемент находится в процессе.

location_id | 1 | 2 | 3 | 4 | 5 | 
--------------------------------- 
10   | 1 | 0 | 0 | 0 | 1 | 
11   | 0 | 0 | 0 | 0 | 1 | 

До сих пор, у меня есть этот запрос:

SELECT count(DISTINCT m.id), l.id, l.name 
     FROM members m 
     INNER JOIN steps s ON m.id = s.member_id 
     INNER JOIN locations l ON s.location_id = l.id 
     WHERE step_no = 5 
     GROUP BY l.id 
     ORDER BY l.name 

Но это только возвращает STEP_NO = 5, конечно же, и если бы я написал пять из этих запросов, член может быть посчитан дважды в разном шаги.

+0

Вещь, которую вы ищете, называется * сводной таблицей *. Я не знаю, как получить его в postgresql, но вы должны искать этот термин. Возможно, вы это выясните. – MarcinJuraszek

+0

Укажите «самый дальнейший» шаг (для каждого члена) - самый высокий идентификатор, самый высокий номер шага, последняя временная метка? –

+0

@ Clockwork-Muse Хороший вопрос. То, что я подразумевал под «самым дальним», - это наивысший номер шага для определенного члена в каждом месте. Например, элемент 2 выше отображается в двух местах. – JHo

ответ

1
select 
location_id 
,sum(case when max_step = 1 then 1 else 0 end) as step_one_cnt 
,sum(case when max_step = 2 then 1 else 0 end) as step_two_cnt 
,sum(case when max_step = 3 then 1 else 0 end) as step_three_cnt 
,sum(case when max_step = 4 then 1 else 0 end) as step_four_cnt 
,sum(case when max_step = 5 then 1 else 0 end) as step_five_cnt 
FROM 
(select 
s.location_id, 
s.member_id, 
max(s.step_no) as max_step 
FROM steps S 
group by 1,2 
) as base 
group by 1 

разбив его, основание запрос дает вам следующий результат:

member_id | location_id | max_step_no 
------------------------------------------------------- 

| 1   | 10  | 5 
| 2   | 10  | 1 
| 2   | 11  | 5 

Запрос агрегации на этот подзапрос (база) в основном сводит результат к форме, которую вы хотели бы видеть. Единственным ограничением этого подхода является то, что количество шагов статически определяется в расширенном.

+0

Это похоже на разумное решение. Мне нужно будет проверить немного больше. Сейчас он возвращает только количество шагов на шаге 5. Статически определенные шаги не являются недостатком для меня. – JHo

+0

Спасибо. Кажется, это хорошо работает. – JHo

+0

Пожалуйста, не группируйте по порядковым номерам столбцов - всегда указывайте имена столбцов в явном виде. –

0

1- Сначала выберите следующее в временную таблицу:

select location_id , step_no , count(member_id) as count 
into  stepsPrime 
from  (select member_id, location_id, max(step_no) as step_no 
      from steps 
      group by member_id, location_id) definedTab 
group by location_id, step_no 
order by location_id; 

2- Используйте следующий запрос, чтобы повернуть вышеуказанные результаты:

select distinct stp.location_id, 
     stp1.count as step1, 
     stp2.count as step2, 
     stp3.count as step3, 
     stp4.count as step4, 
     stp5.count as step5 
from stepsPrime stp 
left join stepsPrime stp1 on stp.location_id = stp1.location_id and stp1.step_no = 1 
left join stepsPrime stp2 on stp.location_id = stp2.location_id and stp2.step_no = 2 
left join stepsPrime stp3 on stp.location_id = stp3.location_id and stp3.step_no = 3 
left join stepsPrime stp4 on stp.location_id = stp4.location_id and stp4.step_no = 4 
left join stepsPrime stp5 on stp.location_id = stp5.location_id and stp5.step_no = 5; 
+0

Извините, две вещи - 1) Я считаю, что postgreSQL поддерживает CTE, поэтому вам не нужна явная таблица temp и 2) вы будете подсчитывать пользователей на шаге _every_, который они сделали, по существу, считая их дважды (или больше!), которые OP явно надеялся избежать. Вам нужно добавить функции OLAP для чего-то подобного ... –

+0

Можете ли вы дать более подробную информацию о том, как подсчитать пользовательский шаг? –

+0

@AmyA Привет, спасибо за ваш ответ. Чтобы подсчитать шаг элемента, я хотел бы получить наивысший номер шага для каждого местоположения. Другими словами, если член имеет несколько шагов в одном и том же месте (member_id 10 выше), то принимайте наивысшие значения. Если у члена есть шаги в нескольких местах, подсчитайте максимальное значение в каждом месте. – JHo