I am attempting at making a site that has a polling section in it. The users need to be able to take previous polls if they have not voted in them yet. So for each poll they take, it adds a note into the cell.
The table looks something like this:
userid | poll1 | poll2 | poll3 | poll4 /
---------+--------+--------+-------+--------/
001 | Y | Y | | /
---------+--------+--------+-------+--------/
002 | Y | | Y | /
--------------------------------------------/
So now, the code would have to select poll 3 and 4 for user 001, and present that to the user on the page. I have been trying a couple different approaches to this but can't seem to find the right code.
I have looked for something for help online and haven't found anything that addresses this issue.
Users
id | name
---+-------
1 | tyrion
2 | cersei
Polls
id | name
---+-------
1 | first poll
2 | second poll
UserPolls
user_id | poll_id
--------+-------
1 | 1
1 | 2
2 | 2
In the above table structure, you have the two main object tables, and one relational table, called UserPolls. This will scale pretty well, for any number of polls you want.
Then, if you want to know which polls were taken by a given user, you can do:
SELECT poll_id FROM UserPolls WHERE user_id = 1
Or if you want the opposite. Polls not taken by a given user:
SELECT id FROM Polls WHERE Polls.id NOT IN (SELECT poll_id FROM UserPolls WHERE user_id = 1)
Note: this is not tested code, but you get the general idea on how to go about designing and normalizing your tables.
Related
Here is my pivot table project_group:
+-----+----------+------------+----------+---------+
| ids | group_id | project_id | admin_id | user_id |
+-----+----------+------------+----------+---------+
| 4 | 115 | 1 | 1 | [3,4,5] |
| 5 | 115 | 2 | 1 | [5,2,1] |
| 6 | 115 | 3 | 1 | [1,3,6] |
This table represent group linked to the projects....user_id is which users can see projects/group... Is there any way to display correct projects/group only to the users defined in user_id?
Also content in user_id field can be changed....
The best way to handle this would be to first normalize your database. Storing comma separated lists in a cell is allowed, but generally bad practice, as explained in this question.
If you can have multiple users per project, you should have a linking table with a column for project and a column for user, like this:
project_users:
| project_id | user_id |
and you can make (project_id, user_id) a composite primary key.
That way, you can select the users for a project (say, project 1) like this:
SELECT user_id
FROM project_users
WHERE project_id = 1;
Once you have these, you can display the project data only to users whose id is returned in the above list.
I have built an SQL Fiddle that helps demonstrate this visually, if it helps.
It is good to note that this proper normalization gives the opportunity to a lot of useful data as well, as it becomes easier to search for users by project, but also you can search for project information based on a user.
I wanted to create a system to track the progress of a player in a game. Each player can be a member of multiple groups, which all have other requirements. In order to track his progress, the stats of the player will be saved once he joins a group. Every time he reloads his stats, the current ones should be saved inside the database.
All stats of the player are stored in a json-format, which will then be parsed either by PHP or JS. An entry with compare = 0 is set once the player joins a group. An entry with compare = 1 should be created the first time a player clicks on Update Stats and from then on it should only be updated, not newly created.
Now my question is: How to achieve that? When reading through the syntax of INSERT INTO I got the following:
INSERT INTO `groups` (`grp`, `id`, `json`, `compare`) VALUES
($grp, $id, $json, 1) ON DUPLICATE KEY SET `json` = $json
However, since there is no key set, and I don't know if I can set up two/three keys (as there can be multiple groups per user, as well as the compare = 0 entry in the same group), I don't think I can do it this way.
+------+----+---------+---------+
| grp | id | json | compare |
+------+----+---------+---------+
| 1 | 1 | stats | 0 |
| 1 | 1 | stats | 1 |
| 1 | 2 | stats | 0 |
| 1 | 2 | stats | 1 |
| 2 | 2 | stats | 0 |
| 2 | 3 | stats | 0 |
| 2 | 3 | stats | 1 |
| 2 | 4 | stats | 0 |
| 2 | 5 | stats | 0 |
+------+----+---------+---------+
grp is the group of the player. There is no real limit set to the
number of groups a player can be in.
id is the ID of the player.
json contains the stats of the player in a json
format (number of points, etc).
compare is a boolean. 0 stands for entry stats (the number of points a player
already had when he registered) and 1 stands for the current stats - Which will
be compared to the entry stats, in order to get the difference (= the points a
player made since joining the group).
I hope my explanation was understandable and someone can help me out.
You can use insert raplace:
REPLACE INTO groups (`grp`, `id`, `json`, `compare`) VALUES (...);
But you must have primary key in table. Replace into automaticly finds out primary key and if record exists, it update row, but if doesn't, it add new row.
You can create a unique key with multiple columns. This will trigger the 'on duplicate' clause.
ALTER TABLE groups
ADD UNIQUE (grp, id, compare)
I am developing a community site for high school students. I am trying to implement a like and unlike system using PHP. Heres what I have got :
A table named likes in MySQL with 3 columns namely app_id VARCHAR(32), user VARCHAR(12), dormant VARCHAR(6).
UNIQUE(app_id,user)
When a person likes a page on my site, a row is either inserted or updated in the likes table with dormant = false.
When a person unlikes a page, the row present is again updated with dormant = true. This is an alternative to deleting the row as it is a bit intensive for a speedy work of likes and unlikes.
I want to know, if I should go for deleting the row instead of updating it, when someone unlikes the page.
Dont Delete the row. Every data you can gather its a valuable data point.
I would say you should create a new record for every unlike also.
These data will be usefull to you in the future to figure out user behaviour.
Some ppl might like smth now and then unlike it , then like it again and so on.
Maybe in the future u would like to see why so many people who liked an item suddely unliked it then liked it again.
So i say gather as much data as you can.
Sounds like premature optimization. Don't do that.
Design your application as you want to use it /as it should work. When it gets busy, find out the bottlenecks and fix them.
If you want to design your application for scalability to the millions, consider using a different database engine / programming platform altogether.
Looks like you haven't record the number of user liked or unliked the pages. In this case, LIKES should be a many table and there should be another table called APPS (or any name you wish) to store pages:
**USER**
+---------+-------+-----+
| user_id | name | ....|
+---------+-------+-----+
| 1 | ... | ... |
+---------+-------+-----+
| 2 | ... | ... |
+---------+-------+-----+
**APPS**
+---------+-------+-----+
| app_id | name | ....|
+---------+-------+-----+
| 1 | ... | ... |
+---------+-------+-----+
| 2 | ... | ... |
+---------+-------+-----+
**LIKES**
+---------+-------+----------+----------+
| like_id |user_id| app_id | is_liked |
+---------+-------+----------+----------+
| 1 | 1 | 2 | 1 |
+---------+-------+----------+----------+
| 2 | 1 | 3 | 0 |
+---------+-------+----------+----------+
Where you can toggle if the user click like( is_liked = 1) or unlike( is_liked = 0) the page
I wish to update one table in my database, the data is from a php POST. (It is a page where multiple edits on rows can take place at once, then it processes them all at once after) and i want it so for each "row" or "loop", it builds a single query that can update all the rows at once.
What i want to do, is in the query, select data from two other tables.
E.g
Posted data:
- Task = "Check current Sponsors"
- User Assigned = "Dan"
- Start Meeting = "Mar 1st"
- Meetings Required = 2
And for User Assigned, i want it to basically do this query:
SELECT id FROM team WHERE fullname LIKE 'Dan'
And for the start meeting, i want it to do this query:
SELECT id FROM meetings WHERE starttime='".strtotime("Mar
1st")."'
-- strtotime() makes a unix timestamp from a string.
but i want it to do that for each "task" that gets submitted. (It is queued up via javascript and it sends them all into the same post request)
Anyone have any ideas on how to do this?
Thanks in advance
Table Structures:
Tasks:
id | startmid | length | task | uid | completed
1 | 2 | 1 | Check Sponsors | 1 | 0
Meetings: (Joined by startmid)
id | maintask | starttime | endtime
1 | Sponsors | 1330007400 | 1330012800
Team: (Joined by uid)
id | fullname | position | class | hidden
1 | Team | All Members | black | 0
2 | Dan S | Team Manager | green | 0
you can use the following construct:
UPDATE mytable( col1, col2 )
SELECT col1_val, col2_val
FROM someothertables
WHERE cond1 = cond1;
For the sake of simplicity in explaining this, imagine a room full of people talking to each other. Every statement made by one person to another would be a record in this table, and all of these records have a unique ID assigned through auto-increment.
However, not everyone in this room is talking to everyone else. There's multiple conversations going on.
These conversations need to be unique amongst themselves. This would prevent a duplicate conversation ID being started, and the site collecting all statements which don't belong to that person.
Or, in graphical representation:
----------------------------------------------
| MessageID | ConvoID | Sender | Recipients | etc...
----------------------------------------------
| 1 | 1 | A | B |
----------------------------------------------
| 2 | 1 | B | A |
----------------------------------------------
| 3 | 2 | C | D |
----------------------------------------------
| 4 | 1 | A | B |
----------------------------------------------
| 5 | 2 | D | C |
----------------------------------------------
| 6 | 1 | B | E |
----------------------------------------------
| 7 | 3 | E | F |
----------------------------------------------
You can actually see the conversations that are taking place here... A talked to B (ID 1), who replied back (ID 2) at around the same time C started a new conversation (CID 2) with D (ID 3).
A finally gets back to B about something (ID 4) and D eventually response to C's earlier inquiry (ID 5). B then talks to E about the same thing he was talking with A about (CID 1) before E turns right around and connects with F to start a completely new conversation.
If this has read like the steps which occur prior to the immediate termination of an employee, it wasn't intended that way, but you're not alone.
So you can see that every DB entry has a unique ID (MessageID), but these messages need to be easily collated together.
The solution I'm seeking is something that allows the DB to create a new and unique "ConvoID". This is why we can't auto-increment, or why we can't force uniqueness on the data set. Duplicates must occur, by nature of what this column is doing, but auto-increment would do, perhaps, the exact opposite of what it is i'm seeking for.
Any help that could point me in the right direction would be significantly appreciated.
Thanks!
You could normalize the design by adding a Conversations table. The table would have its own auto-incrementing column. Whenever a new conversation is started, you add a row to Conversations, and use its identifier as ConvoID.