Creating a waiting listing system and re-ranking users - mysql

So here is my problem, I am working on a wait listing system for an app. A user would sign up to be notified when we launch, and offer referral links to help "boost" their spot in the wait list.
The problem I am having is how should I rank them inside of a MySQL or NoSQL database. The issue I am running into is this, if my database looks like this:
User | Ranking | Invited
-------------------------
user1 | 1 | 0
user2 | 2 | 0
user3 | 3 | 0
user4 | 4 | 0
user5 | 5 | 0
user6 | 6 | 0
user7 | 7 | 0
user8 | 8 | 1
Now, assuming user8 now invites 1 friend. They get bumped up to the top, but how do I go about sorting this data? It is fine reordering the entire table to look like this:
User | Ranking | Invited
-------------------------
user1 | 2 | 0
user2 | 3 | 0
user3 | 4 | 0
user4 | 5 | 0
user5 | 6 | 0
user6 | 7 | 0
user7 | 8 | 0
user8 | 1 | 1
But not very practical if the records go over a few hundred. Maybe I am not looking at this problem the right way? There must be a simpler solution? Any pointers or help is appreciated! Thank you.

If you want the ranking to be based on who has invited the most people, and if the same number of invites, their original rank, just sort that way when you read the table:
select user from waitlisttable order by invited desc, ranking;
If you need that order in some larger query, you could create a view for that, but actually updating the rankings for all existing records should definitely be avoided.
If you want to get the "rank" for all the users, see How to show sequential number in MySQL query result.
If you really need to be able to look up a single user's rank, then you probably do need to update all the rows; depending on how heavy your load is, you would either do so every X minutes by some job, or each time a row is updated via a trigger. A simple example of doing the former would be:
set #rank:=0;
update waitlisttable set ranking=(#rank:=#rank+1) order by invitations desc, initial_ranking;

Related

Users queue in mysql

I'm trying to create queues table
id | queue_id | user_id | is_active_to_vote
1 | 14 | 1 | 1
2 | 14 | 2 | 0
3 | 14 | 3 | 0
4 | 15 | 1 | 1
5 | 15 | 2 | 0
6 | 15 | 3 | 0
the users list in result looks like this (for queue_id=14)
Sam (user_id=1 votes now)
John (user_id=2)
Bill (user_id=3)
But if user did not vote in time I need to resort the queue like this
John (user_id=2 votes now)
Bill (user_id=3)
...
Sam (user_id=1 last user in queue)
What is the good way to do this?
Since you're using "did not vote in time" information in order to sort your queue, you need that information on voting time somewhere - either in a new field in your current table, or in a separate table.
Once you have that, you'll be able to sort the queue based on the criteria you want (which aren't clear to me at this point - is it user_id by default ?).
Note that in general I would advise you to perform queue management in your application controller, not directly in MySQL.

How to maintain read/unread messages by php

This question might have been asked many times before this post, but I could not find a suitable answer which perfectly did what I want.
Suppose I have two tables:
table-1: table_msg
-------------------------------------------------------
msg_id | msg_subject | create_time
-------------------------------------------------------
1 | welcome to this site | 2015-01-01 10:20:30
-------------------------------------------------------
2 | How to visit this site | 2015-01-05 10:30:00
--------------------------------------------------------
3 | Plz pay your member fee | 2015-03-10 09:00:00
--------------------------------------------------------
4 | Important Notice | 2015-06-01 12:20:00
--------------------------------------------------------
5 | Plz change your password| 2015-06-15 13:24:01
--------------------------------------------------------
table-2: table_user
-------------------------------
user_id | last_login
-------------------------------
1 | 2015-03-01 07:00:00
-------------------------------
I see solutions almost all the time, that as user_id-1's last login was before msg_id-3, so if the user_id-1 logins on 2015-06-02, he has 02 new messages msg_id-3 and msg_id-4. Well I can bold the subject of these two messages by css to show it as UNREAD. Now suppose after login user_id-1 opened msg_id-4 and did not opened msg_id-3, so the msg_id-3 is still UNREAD.
Now when the same user again login on 2015-06-20, then after his last login, msg_id-5 can be easily identified as UNREAD as it was posted after his last login 2015-06-02, it can be made bold, but what about msg_id-3 which was posted before his last login but still not opened. It is also UNREAD and should be in Bold font.
How can I identify msg_id-3 as UNREAD without a separate table like below:
table-3: read_msg
------------------------
id | user_id | msg_id
------------------------
1 | 1 | 1
------------------------
1 | 1 | 2
------------------------
1 | 1 | 4
------------------------
table-3 is well for a few users, but if users are 5000 in numbers and total messages are 10000 or higher then the table would be a quite large to handle for mysql engine and it will grow geometrically larger even day by day.
Is there any mechanism/technique or algorithm so that together with message that were posted after last login, message which were not opened before last login can also be identified as UNREAD without a huge size read_msg table?
why not just add a column (boolean) with the status (1 = read, 0 = unread) to your table, which upon opening a certain message updates the status to read.
table-3: read_msg
id | user_id | msg_id|read
1 | 1 | 1|0
1 | 1 | 2|1
1 | 1 | 4|0
consider the following scenario:
A user logs in and has 7 unread messages. he chooses to read only 1. If you create a query/algorithm to use his last login time to see unread messages, it will see that he logged in after the messages were posted. but did he read them? no ...
I just noticed that, as you've described, you have one table that has the messages. These messages are for everyone. I think that davejal assumes, as I did, that these messages were directed towards each user. In which case, you would have one row in table_msg per message per user. To get the messages for that particular user, the table would have to be:
msg_id | msg_subject | create_time | read |user_id|
--------------------------------------------------------------------------
1 | welcome to this site | 2015-01-01 10:20:30| 0 | 1
--------------------------------------------------------------------------
2 | How to visit this site | 2015-01-05 10:30:00| 0 | 1
--------------------------------------------------------------------------
3 | Plz pay your member fee | 2015-03-10 09:00:00| 1 | 1
--------------------------------------------------------------------------
4 | Important Notice | 2015-06-01 12:20:00| 1 | 1
-------------------------------------------------------------------------
5 | Plz change your password| 2015-06-15 13:24:01| 0 | 1
----------------------------------------------------------------------
Then you would simply do:
select * from table_msg where user_id = 1 and read = 0;
This is the only way I can think of that would avoid having the third table read_msg. The table can get large as some messages will be duplicated, but you can always delete old read messages if you're concerned about that.

How to create mysql db for account balace, add and subtract amounts

I have project like online service, i have made some part and stopped. If user use service it must take some amount (e.g. 5$ per service). I don't know how to build MySQL tables. I have made 2 tables 1st for rest amount 2nd for add and subtract amounts. May be this is wrong way, what is the best practice?
action_table
id | userId | reason | amount
1 | 4 | for service 3 | -5
2 | 2 | refill account | 100
3 | 13 | for service 3 | -5
balance_table
1 | 4 | 23
2 | 2 | 125
3 | 13 | 0
After using service query adds one row to action_table and updates balance_table
Personally, if I was making an account database, I would have one table for an account and one for transactions, like this:
Accounts:
| id | user | name | balance |
Transactions:
| id | account_id | description | amount | is_withdrawal |
The reason I came up with this is because it helps to think of database tables like real world objects sometimes, and in this case you have a Transaction and an Account.
Then, you can use a TRIGGER to update the account table anytime you add a transaction.

mysql user row level access

Have a database with the following
id | userid | name
1 | 1 | John
2 | 1 | John
3 | 2 | Joe
4 | 2 | Joe
5 | 2 | Joe
6 | 3 | Sue
7 | 3 | Sue
I need to get a way that I can create a database, then create users. Each user that I create in mysql limit them to access of data for their userid. Every database table in the database has the userid value.
So whether they are reading ,updating, insert or delete. If it is going through a specific mysql user that I attached to that database, I want that user to only read, update, insert or delete where their userid is.
I have read some things on mysql triggers but have not found anything that will work for me.
We have a backend that has data in it and restricted by userid.
The website pulls data from that table based in userid so select * from articles where userid=1. Right now, that code is modifiable by the user. I would like a way to go select * from articles and mysql only results rows that have userid=1 for that mysql user. The goal would be for every user to have their own mysql user login to the mysql database that would restrict to that specific value of userid that is theirs.
Any thoughts? Thanks so much!
GoogleResult[0] has this:
http://www.sqlmaestro.com/resources/all/row_level_security_mysql/
Abstract
The article contains a step-by-step guide to implementation of row level security in MySQL 5.0 and higher using such MySQL features as views and triggers.
Well! i will suggest to make a table for that. For the whole application
user_rights
id | user_id | insert | update | delete | read
1 | 2 | 0 | 0 | 0 | 1
Note : 1 for allowed and 0 for disallowed.
Now before you do anything first check the rights then perform other actions.
Detailed method including parts of application :
screens
id | title
1 | articles
2 | blog
user_rights
id | user_id | insert | update | delete | read | screen_id
1 | 2 | 1 | 0 | 0 | 1 | 1
2 | 2 | 0 | 0 | 0 | 1 | 2
In this method you can allow screen level access. User id 2 can add and view articles and he can aslo view blog but.
I may be using inappropriate terms here
but i hope you get the idea.

How to update a 'Sort Index' column of a list of records with one call

Basically, I have a list of records in a mysql db. These records are ordered 1 to 10. The user can re-order these records to whatever order they want. They will press a button to update all the records to their newly, respective order number. For example:
ID | Sort_Index | Name
----------------------
1 | 1 | Jim
2 | 2 | Bob
3 | 3 | Carl
4 | 4 | Bill
5 | 5 | Wendy
The user can change these to this for example:
Note: the changed values are stored into an array before I make the UPDATE calls
ID | Sort_Index | Name
----------------------
1 | 1 | Carl
2 | 2 | Wendy
3 | 3 | Bob
4 | 4 | Jim
5 | 5 | Bill
My question is, how can I make this mysql call with one call, using the new values in my array, instead of one call for each record?
If this is impossible or simply the "wrong way to do it", please feel free to suggest new ideas as I am not fully committed to this idea as of now.
If you have a limited number of rows, you could implement this with an sql CASE statement --
Update users set sort_index = case id when 1 then <newval> when 2 then <newval>...