2015-01-30 2 views
4

Имея трудное время, ставя то, что я пытаюсь сделать словами, поэтому поиск также затруднен.Проверьте, существует ли значение в столбце для каждой группы.

В основном я пытаюсь выяснить, существует ли определенное значение в столбце, разбитом на группы, и затем распространять это значение вперед.

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

pk | user | ... | activity 
1 | A | ... | "login" 
2 | A | ... | "started_tutorial" 
3 | A | ... | "completed_tutorial" 
4 | A | ... | "some other activity" 
5 | A | ... | "logout" 
5 | B | ... | "login" 
6 | B | ... | "logout" 

Я думаю, что это должно быть что-то вроде

select *, 
    check(activity in ('completed_tutorial')) as completed_activity 
    from tbl 

, но я не думаю, что я могу использовать check в операторе отбора и это будет постоянным, а не флаг установлен верно только после него был найден.

Пример того, что я пытаюсь получить:

pk | user | ... | activity    | completed_tutorial 
1 | A | ... | "login"    |     0 
2 | A | ... | "started_tutorial" |     0 
3 | A | ... | "completed_tutorial" |     1 
4 | A | ... | "some other activity" |     1 
5 | A | ... | "logout"    |     1 
5 | B | ... | "login"    |     0 
6 | B | ... | "logout"    |     0 

ответ

3

Вы можете выбирать группы SQL с HAVING clause. Например, вы можете сгруппировать таблицу пользователей и их активности, а затем процеживают содержать только те, которые завершили учебник:

SELECT user FROM tbl 
GROUP BY user, activity 
HAVING activity = 'completed_tutorial'; 

EDIT: После OP отредактировала свой вопрос, это мой новый ответ. Здесь я предполагаю, что в вашей таблице есть поле даты.

SELECT *, COALESCE(date >= (
    SELECT date FROM tbl WHERE activity = 'completed_tutorial' 
    AND user = outertbl.user 
), FALSE) 
FROM tbl AS outertbl 
ORDER BY date 

Обратите внимание, что такой запрос является по существу N² когда unoptimised, поэтому я бы рекомендовал вместо того, чтобы просто получить данные из базы данных, а затем обработать его в программе.

+0

Это полезно, но я не хочу фильтровать/удалять строки. Вместо этого я хочу иметь индикатор для каждой строки, чтобы определить, произошло ли это действие или нет. – user12202013

+0

@ user12202013 См. Править. –

1

вы могли бы попробовать что-то вроде этого

SELECT a.*, coalesce(b.completed, 0) 
FROM tbl a 
LEFT JOIN (SELECT user, 1 completed 
      FROM tbl 
      WHERE user = a.user 
       AND activity='completed_tutorial') b 
ON a.user = b.user AND b.pk >= a.pk 

это предполагает, что существует не более одной строки с activity='completed_tutorial' и что пользователь идентифицирует «сеанс». вам нужно будет добавить другое поле, если пользователь может сделать более одного учебника.

+0

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

+0

Таким образом, создается впечатление, что «активность» является «завершенным», но не распространяет индикатор вперед. :( – user12202013

+0

, что вы подразумеваете под «распространением вперед»? Он присоединится ко всем записям с соответствующим «завершенным_историком», если он существует. – 1010

1

Я не уверен в скорости этого, но как насчет следующего решения?

SELECT 
    user 
    ,max(CASE 
      WHEN activity = "completed_tutorial" THEN 1 
      ELSE 0 
      END) AS completed_tutorial 
    FROM tbl 
    GROUP BY user 
;