#oracle #row #next #lead
Вопрос:
У меня есть таблица игроков в качестве игрока 1, где я хочу получить количество людей, которые вошли в систему второй день подряд. Так что в моем случае результат будет 2, так как 2 человека вошли в систему второй день подряд. Я попробовал следующее выбрать количество(*) из ( выберите идентификатор игрока из группы player1 по идентификатору игрока, у которого количество(идентификатор игрока)>1 по идентификатору игрока ) присоединиться к игроку 1 b на.идентификатор игрока=b.идентификатор игрока и b.дата входа в систему (b.дата входа в систему, (b.дата входа в систему 1))
Но это касается всех строк, то есть 9 строк
Комментарии:
1. Ваши примерные данные не имеют смысла. В некоторых строках ИДЕНТИФИКАТОР игрока = 3 имеет ИМЯ = Джейк, в других тот же идентификатор имеет ИМЯ = Джон. Тогда почему вы не хотите, чтобы что-то возвращалось для последних двух строк в таблице? Идентификатор ИГРОКА = 4 вошел в систему 11/1 и 11/2 дней подряд. Наконец, для уточнения: если один и тот же игрок входит в систему в последовательные дни более одного раза (скажем, 8/20 и 8/21, а затем также один и тот же игрок, 9/03 и 9/04), хотите ли вы считать каждое событие отдельно или это просто 1 (для «отдельного игрока, который вошел в систему в последовательные дни один раз или, возможно, более одного раза»)?
2. Извините, что я экспериментировал, вот почему я столкнулся с этой проблемой. Я отредактировал свой вопрос, пожалуйста, помогите, когда у вас будет возможность
3. Я хотел ,чтобы результат был таким, как 2, поскольку 2 человека в таблице вошли в систему последовательно в течение нескольких дней с самой ранней даты их входа в систему, другие вошли в систему, но не в течение нескольких дней с самой ранней даты их входа в систему
4. … но теперь (после изменения ваших выборочных данных) у вас есть игроки, которые вошли в систему в один и тот же день — действительно ли это возможно в ваших реальных данных? И если да, то считается ли это «вторым входом в систему», или это должно быть в разные дни — в самый ранний день и на следующий день? Обратите внимание, что в исходном сообщении и в измененном вы нигде не упоминали, что последовательные входы в систему должны включать самую раннюю дату.
5. Нет, я намеренно вошел в dups, но хочу только подсчитать игроков, имеющих самую раннюю дату 1 в данных, мог бы найти решение, как показано ниже, пожалуйста, дайте мне знать, если есть какой-либо другой способ его достижения
Ответ №1:
В Oracle 12 и выше вы можете легко сделать это с помощью match_recognize
:
select count(*)
from player1
match_recognize(
partition by player_id
order by log_in_date
pattern (^ first_date same_day* next_day)
define next_day as log_in_date = first_date.log_in_date 1
);
Имена в pattern
предложении (и в define
) предоставляются по нашему усмотрению (мы создаем эти имена так же, как мы можем давать псевдонимы таблицам или столбцам в запросе). Они используются для классификации строк — либо как «first_date», «same_day» (как первая дата), либо «next_day» (после начальной даты входа в систему). Привязка ^
означает, что совпадение начнется с самой ранней даты в каждом разделе (это используется точно так же, как и в регулярных выражениях для строк).
match_recognize
обучение требует времени (для программистов, которые еще не знают и не используют его), но оно того стоит.
Комментарии:
1. Спасибо за ваш ответ, но, к сожалению, у меня есть только 11g
Ответ №2:
Я смог получить ответ, как показано ниже:
select count(distinct dt) from (
select player_id, min(log_in_date) 1 dt
from player1
group by player_id
having count(player_id) > 1
) A join player1
on player1.player_id = a.player_id
where player1.log_in_date = dt
Есть ли более простой способ сделать это? Пожалуйста, дайте мне знать.
Комментарии:
1. Выберите код, который вы опубликовали. Затем либо нажмите CTRL-K на клавиатуре, либо нажмите кнопку
{}
форматирования вверху. И то, и другое приведет к тому, что код будет отформатирован как код.