2012-02-28 1 views
3

私のAndroid Appでは、データベーステーブルに保存されている連続した日付のうち、最も長いストリークと現在のストリークを追跡する必要があります。私はこれを動作させるためにどこから始めるべきかさえ知らない。私が思いつくことができる最高ののは、テーブル内のすべての行をクエリし、それらのすべてをプログラム的に反復してギャップがどこにあるのかを見つけることです。あまり効率的ではありません。誰もが良いアイデアを持っていますか?テーブル内の連続する日付の数をどのように数えますか?

+1

おそらく、このリンクはあなたにいくつかのアイデアを与えるだろう。http://stackoverflow.com/questions/3049586/how-to-calculate-longest-streak-in-sql – gangreen

答えて

1

ここは、私が本当にクールだと思ったSQLの唯一の解決策です。あなたのテーブルの日付がユニークであると仮定すると(それをグループ化することは難しくありません)、http://www.sqlteam.com/article/detecting-runs-or-streaks-in-your-dataから適応された方法を使用することができます。私はこの例題を使いましたが、いくつかの構文エラーがありますので、私は以下の答えでそれらを繰り返さないことを願っています。私はおそらくいくつかの予約語を使用していたので、それを適応させる必要があるかもしれません。

まず、あなたのニーズをカバーするために非常に大きな日付の表を作成します。私はSQLiteの最良の方法は何か分かりませんが、SQL ServerではDatetimeフィールドに整数を挿入することができ、整数から暗黙の日付変換を行います。テーブルに整数を挿入する方法はたくさんあります...

とにかく、Datesテーブルが作成されたら、あなたのStreakテーブルの最小値と最大値を範囲として使用して、DatesテーブルからStreakテーブルへの左結合を行いますリミッタ。あなたは次のコードを持っています。のはのは、あなたがのようないくつかのかなりクールなものを行うことができます。この時点で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) 

次の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を呼ぶことにしましょう

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 0それを呼び出す てみよう答え: 最長ストリークは何でしたか?

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 
+0

ありがとう、それは多くの助けになります。 – Nick

1

基本的に月と月が であるため、日数を必要な数と比較するだけです。

ギャップがある場合は、1か月の数から数を差し引くと簡単に見つけられます。例えば。あなたはcount(days_visited) where month=1 を持っており、それは20日、あなたを返しますがJanuary has 31ので、11日にギャップがありますし、sqliteの

の日付関数をhere're

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

をあなたは以下の機能に EDIT

SELECT date('now','start of year','+9 months','weekday 2');などを使用することができます

申し訳ありませんすべてのソリューションは醜いです。それは私が知っている。


create table visits(day_visited timestamp、visited int); を示す表を毎日作成すると、ユーザーがオンラインかオフラインかにかかわらず、 'now',1 or 0(オンライン/オフライン)のレコードが作成されます。その後、あなたはそこに記録を走らせます。 月のレコードは、1と0を持つint配列になります。

 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  

マップやテーブルは月のために=オンライン、オフラインの日のペアが含まれています: はvistedrecordsformonth

擬似コードと呼ばれます。 と を比較すると、オンラインまたはオフラインで最大のストリークが何であるかを確認できます。

これは醜い私は確かにあるよりエレガントな何かがあるはずですが、 としてそれは動作するはずです。


欲しいと思っています。

+0

私はまだわからないどのように私ができますそれを使用してください。今日が1/9で、私のデータベースに日付が1/1、1/2、1/3、1/4、1/5、1/7、1/8、1/9(毎日1/1と1/9を除いて1/9)、最長のストリークでは5、現在のストリークでは3が必要です。合計数をチェックすると、9日間のうち8が与えられますので、ギャップがあることがわかりますしかし、それは私に最長かつ現在のストリークカウントを与えません。 – Nick

+0

あなたの日付を数週間に分割することができます。また、それに応じてストリークを評価することもできます。 '%w曜日0-6 sunday == 0%W week of year 00-53'を使用してください。 –

+0

簡単な方法は、 'days_visited'と' days_loggedoff'を使ってテーブルを作ることです。 –

関連する問題