商城接到一個需求,有以下幾個要求:
增加簽到的功能,1號簽到增加1個積分,2號簽到增加2個積分,以此類推。
連續簽到第6日,15日,25日分別獎勵積分50,70,100個積分。
每天能補簽一次。
使用者能查看曆史幾個月的簽到記錄。
簽到好做,用ajax提交就好。
可是問題是:根據以上需求,怎麼儲存資料較好。
第一種:
把簽到的日期放在sign_record
中,以逗號隔開。
user_id |
date_month |
sign_record |
1 |
2015-08 |
1,2,3,4,5,7,8,9,10... |
2 |
2015-08 |
7,8,9,10... |
3 |
2015-08 |
1,7,8,9,10... |
... |
... |
... |
第二種:
把簽到的日期放在sign_record
中,
user_id |
date |
sign_record |
1 |
2015-08 |
1 |
1 |
2015-08 |
2 |
1 |
2015-08 |
3 |
1 |
2015-08 |
4 |
2 |
2015-08 |
2 |
... |
... |
... |
第三種:
上面兩種的話我偏向於第一種,但是可能不符合三範式。
有沒有其他的方式來儲存呢,請大大們支招。
回複內容:
商城接到一個需求,有以下幾個要求:
增加簽到的功能,1號簽到增加1個積分,2號簽到增加2個積分,以此類推。
連續簽到第6日,15日,25日分別獎勵積分50,70,100個積分。
每天能補簽一次。
使用者能查看曆史幾個月的簽到記錄。
簽到好做,用ajax提交就好。
可是問題是:根據以上需求,怎麼儲存資料較好。
第一種:
把簽到的日期放在sign_record
中,以逗號隔開。
user_id |
date_month |
sign_record |
1 |
2015-08 |
1,2,3,4,5,7,8,9,10... |
2 |
2015-08 |
7,8,9,10... |
3 |
2015-08 |
1,7,8,9,10... |
... |
... |
... |
第二種:
把簽到的日期放在sign_record
中,
user_id |
date |
sign_record |
1 |
2015-08 |
1 |
1 |
2015-08 |
2 |
1 |
2015-08 |
3 |
1 |
2015-08 |
4 |
2 |
2015-08 |
2 |
... |
... |
... |
第三種:
上面兩種的話我偏向於第一種,但是可能不符合三範式。
有沒有其他的方式來儲存呢,請大大們支招。
剛好我以前做過類似的一個資料庫設計,給你一個思路
這個明顯是需要兩張表來進行共同儲存(就是把你的第一張表跟第二張結合)
表A儲存的為
| userid | lastsign| consigncount |
| 1 | 2015-08-28 | 2 |
這個consigncount儲存的是使用者連續簽到的天數
表B跟你表二的結構一樣
這其實是兩個需求,一個需求叫連續簽到獲得積分,另一個需求叫查看簽到記錄
表A你可以理解為統計表
每次使用者簽到的時候判斷邏輯為
1使用者簽到 2查詢表B判斷是否為連續簽到(查詢昨天的簽到記錄)
2.1 true 使用者連續簽到天數+1,並計算簽到積分 2.2 false 2.2.1 判斷是否補簽(不太清楚你補簽的需求是怎樣,是前天簽到的話就查詢記錄) 2.2.1.1 true 補簽邏輯 2.2.1.2 false 將使用者的連續簽到天數重新置為1 3在表二中插入一條今天的簽到的資料記錄
流程結束
sign(user_id,date_month,sign_records)
我也認同樓主採用第一種.
因為查詢的條件主要還是落在user_id
和date_month
上,
然後拿到使用者的簽到記錄sign_records
,
再用explode以逗號分割轉成數組進行積分計算.
建議date_month
使用時間戳儲存:
strtotime('2015-08')
得1438358400
欄位類型剛好可以選擇int(10),同時建立索引,加速查詢.
因為簽到記錄sign_records
都是整數,可以用intval()
保證插入的值是整數.
以逗號分隔存入欄位並無不妥,省去了序列化或者JSON的編解碼操作,同時還方便使用MySQL的FIND_IN_SET
函數以sign_records
欄位為條件進行查詢,這都是逗號分隔的好處:
比如查詢在8月1日簽到的使用者:
SELECT `user_id` FROM `sign` WHERE `date_month` = 1438358400 AND FIND_IN_SET('1', `sign_records`);
個人見解是:
1.資料表的欄位“datamonth”改為“dataday”按天來記錄簽到。
2.具體的分值根據簽到天數計算:
a.比如:初始分值設為1,第二天簽到的同時更新使用者的簽到分值,並且判斷使用者前一天是否簽到。如果簽到則第二天分值增加比前一天多1分。b.當增加的分值等於6時,表示使用者連續簽到了6天,則給當天的分值增加(1+49)[其中的"1"表示每天增加1,49是常數,為了湊要求的分值]分c.當增加的分值等於15時,表示使用者連續簽到15天,則給當天的分值增加(1+69)分。d.其他一次類推。
我不是大神,只是說說我的看法。
使用JSON儲存
MySQL的話建議用JSON, MySQL 5.7原生JSON格式支援.
用某種符號進行分割建議盡量避免, 日期比較簡單. 如果複雜的資料就很容易出錯. 能有穩健的資料結構就用資料結構.
使用觸發器
可以使用觸發器來處理積分什麼的.
第一種,但是增加一個欄位,就是連續簽到次數,補簽應該是出發比較少的行為吧