Как вы считаете количество последовательных дат в таблице? - PullRequest
3 голосов
/ 28 февраля 2012

В моем приложении для Android мне нужно отслеживать самую длинную и текущую серию последовательных дат, которые сохраняются в таблице базы данных. Я даже не знаю, с чего начать, чтобы это заработало. Лучшее, что я могу придумать, - это запросить каждую строку в таблице и программно перебрать все из них, чтобы найти пробел. Не очень эффективно. У кого-нибудь есть идеи получше?

Ответы [ 2 ]

1 голос
/ 28 февраля 2012

Вот решение только для SQL, которое мне показалось действительно классным. Предполагая, что даты в вашей таблице уникальны (не то, чтобы просто было сгруппировать их), вы можете использовать адаптированный здесь метод http://www.sqlteam.com/article/detecting-runs-or-streaks-in-your-data. Я пробежался по примеру и есть некоторые синтаксические ошибки, так что, надеюсь, Я не повторял их в своем ответе ниже. Вероятно, я использовал некоторые зарезервированные ключевые слова, поэтому вам может потребоваться адаптировать его.

Сначала создайте таблицу дат, которая будет достаточно большой, чтобы удовлетворить ваши потребности. Я не уверен, что лучший метод для SQLite, но в SQL Server вы можете вставить целые числа в поле Datetime, и он будет выполнять неявное преобразование целых чисел в даты. Есть много способов вставить целые числа в таблицы ...

В любом случае, после создания таблицы Dates выполните левое соединение таблицы Dates с таблицей Streak, используя минимальные и максимальные даты из таблицы Streak в качестве ограничителя диапазона. Затем у вас будет следующий код. Давайте назовем это SQL 0

SELECT Dates.Date,
       CASE 
         WHEN StreakTable.DATE IS NULL THEN 0 
         ELSE 1 
       END AS Result 
FROM   Dates 
       LEFT JOIN StreakTable 
         ON Dates.DATE = StreakTable.DATE 
WHERE  Dates.DATE BETWEEN (SELECT MIN(DATE) AS MinDate 
                           FROM   StreakTable) AND (SELECT MAX(DATE) AS MaxDate 
                                                    FROM   StreakTable) 

Давайте назовем следующий SQL 1

SELECT Date, 
       Result, 
       (SELECT COUNT(*) 
        FROM   (SQL 0) S 
        WHERE  S.Result <> SV.Result 
               AND S.GameDate <= SV.GameDate) AS RunGroup 
FROM   (SQL 0) SV 

Давайте назовем следующий SQL 2

SELECT Result, 
       MIN(Date) AS StartDate, 
       MAX(Date) AS EndDate, 
       COUNT(*)      AS Days 
FROM   (SQL 1) A 
GROUP  BY Result, 
          RunGroup 
ORDER  BY MIN(Date) 

На данный момент вы можете сделать несколько очень интересных вещей, таких как ответ Какой была самая длинная полоса?

SELECT TOP 1 * 
FROM   (SQL 2) A 
WHERE  Result = 1 
ORDER  BY Games DESC 

Какая текущая полоса на последнюю дату?

SELECT *  
FROM (SQL2) A 
WHERE EndDate = (SELECT Max(Date) 
FROM Streak)

Сколько полос 3 или более у нас было?

SELECT Result, 
  COUNT(*) as NumberOfStreaks 
FROM (SQL 2) A 
GROUP BY Result 
WHERE Days >= 3
1 голос
/ 28 февраля 2012

Обычно у вас есть месяц и дни в месяце, поэтому вы просто сравниваете количество дней с необходимым числом.

Если есть разрыв, вы можете легко найти его, вычтя количество дней в месяце.Например, у вас есть count(days_visited) where month=1, и он возвращает вам 20 дней, но January has 31, поэтому есть разрыв в 11 дней, и вот функции даты в sqlite

http://www.sqlite.org/lang_datefunc.html

Вы можете использовать следующие функции, такие как SELECT date('now','start of year','+9 months','weekday 2');

EDIT

извините, все решения безобразны.это я знаю.


создание посещений таблицы (отметка времени day_visited, посещение int);В этой таблице вы ежедневно создаете запись, указывающую, был ли пользователь онлайн или оффлайн с 'now',1 or 0 (онлайн / офлайн).Затем вы пробегаете туда записи.Ваши записи за месяц будут массивом с 1 и 0.Позывной vistedrecordsformonth

псевдокод:

      int online=0;
      int offline=0;     
for(int i=0;i<vistedrecordsformonth.size();i++){    
      boolean flag=false;         
   if(vistedrecordsformonth[i]==1){ //visited
      if(!flag&&i!=0) //check for flag and not 0 index to insert a record
      {
      streaksMap.put(online,offline); //or insert a record into another streakmap or table 
      online=0;
      offline=0;     
      }
      flag=true;
      online++; 
   }
   else{
      flag=false;
      offline++;
   }
} //end of for    

Карта или таблица будет содержать пару дней онлайн = дней в течение месяца.с обычным order by вы можете увидеть, что было самой большой полосой в онлайн или офлайн днях.

Ужасно, я знаю, я уверен, что должно быть что-то более элегантное, но как бы быстрое и грязное оно не сработало.


надеюсь, что это поможет abit.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...