I have several tables that i need to create an admin interface for
Table 1
Table 2
Table 3
Table 4
Table 5
each table's contents are reflected of which parent it belongs to in a field...so
table 2, has a field for which row in table 1 it relates to, table 3 has a field for relating to table 2 and so on.
Whats the best way to present this to the user so they dont have to memorize id numbers. Say for instance, they want to add a new entry in table 3, they must select which row in table 2 to link to.
The relationship only extends one level above after table 1. So creating a new set of options in table 5, would involve creating an entry in table 1, new entry in table 2, linking it to table 1, new entry in table 3, linking it to table 2, new entry in table 4, linking it to 3, and finally the new option in table 5.
So my question is user-interface related as to the best way to present this to the user. Alternatively, what is this kind of system called, so i can search for other examples.
Thanks.
From what you're saying, it looks like it's not possible for one entry in a table to exist without the corresponding entries in the other tables, right?
In that case, you could present a wizard like interface which prompts the user to enter the data for each table on each new wizard page, starting from the data for table 1. Then once all the data has been collected, you can fire off a series of update statements where the id of the record in table 1 is reused for the inserts in tables 2-5. (Depending on your table design, you might get this id using LAST_INSERT_ID()).
Or if you don't want to use multiple insert statements, you might use an updateable view (if you're using MySQL 5).
Alternatively, you could have a table structure where a record in table X must have a linked record in table Y (where Y < X). In other words, a record in table 1 may not have a linked record in table 2, but a record in table 2 must have a linked record in table 1.
In this case, you can still use the wizard, but you can start with the table that you actually want to create information for, then have the wizard prompt for data for the previous table, and so on until it prompts for data for table 1. So if you really want data to be created for table 4, have the wizard prompt for that first, then prompt for data for table 3, and so on up to table 1. Then do the data entry as before.
Sounds like a problem ready-made for my old favorite, the master-detail layout. Each table is represented in a separate pane (Panes 1 through 5) displayed in the same window. The panes are arranged top-to-bottom and/or left-to-right for Tables 1 through 5 sequentially. In each pane, there is always exactly one “active” record, which is marked for the user in some way. The contents of each pane are determined by the active records in the panes above/left of it. Thus, Pane N shows the Table N records for the active record of Table N-1 shown in Pane N-1. The active record in a pane is whichever record in the table last had focus (in any field). Thus, for example, the user can display the Table N records for a particular record in Table N-1 by clicking on any field for that record in Pane N-1. Queries for Pane N are launched asynchronously once the active record changes in Pane N-1 (no “Refresh” button, please). All non-read-only fields should be edit-in-place. A Save button or menu item inserts/updates all records of all tables as a batch (alternatively, you can fire an Update whenever a field is edited and focus leaves it, if your bandwidth can handle it).
Thus, to add a new record to Table N, the user places focus on the correct records for Table 1 through Table N-1, then places focus in Pane N (e.g., click anywhere in it) and selects the Add Record menu item. This inserts a new blank record in Pane N for the user to complete. The user can continue to select Add Record to fill Pane N with the desire records for the active Table N-1 record. At any time, the user can use the same process to add Table N+1 records for a newly created Table N record by clicking on Pane N+1 and selecting Add Record. Also, at any time, the user can edit the fields of the records in any pane. (Alternatively, you can have separate Add Record menu items for each table, which saves the user having to shift focus to a pane to add records, but that many menu items can get more cluttering than its worth; another approach is to always have a blank record in each pane ready for the user to fill out, eliminating the need for the Add Record menu item).
This design provides the users with the most flexibility, allowing them to add, delete, and update records in any order convenient for any table at any time. Because the window “remembers” the active records between edits, it’s also very efficient, eliminating the tedious re-selecting of Table 1 through N-1 records to edit a series of Table N records for a particular Table N-1 record (unlike, say, a wizard). It displays all the records for all tables in a single window in an intuitive hierarchical layout that facilitates viewing and exploring the data and minimizes navigation among windows or pages (again, unlike a wizard).
Five panes is a lot for a single window, but not too much. However, it would help if you provided easy ways for users to resize and hide/show each pane. Thus, if the user needs to work on a bunch of Table N records of a record in Table N-1, she or he can hide all the other panes, expanding Pane N to full window size to minimize scrolling. Also, if the user does not ever need to study or edit the records of some of your tables, do not put them in panes of their own, but rather make each appear as a field for the adjacent table in the structure. For example, if the users aren’t allowed to edit Table N, then instead of Pane N you can have a field in Pane N+1 that displays the functional name of the Table N record that each Table N+1 record belongs to. By making it a drop-down list, user will be able to assign/re-assign the Table N record for any Table N+1 record.
Details at http://www.zuschlogin.com/?p=31.
More stuff at Stack Overflow than may be relevant:
Hierarchy Visual Design
UI design pattern for multi level grid
What’s best when inserting into a table view, and add button or a blank line?
Related
I'm creating a carousel/image slider plugin for WordPress and I've hit a wall. There's going to be an indefinite amount of user input and I need to know how to handle this.
I currently have six static inputs: transition_time, loop_carousel, stop_on_hover, reverse_order, navigation_arrows, and show_pagination and the variable amount of info will come from the images the user wants to use. So this could be anywhere from zero to infinite.
I want to be able to create/delete X amount of columns in the DB.
So starting out there will be zero images, meaning six columns. If a user adds two images I want to have eight columns, two created. If the user deletes them then I want to go back to my original six.
I'm guessing this is possible but how and is this a good idea or should I just have a set amount of images?
You Are Doing It Wrong™.
Changing a table definition should be an exceptional event.
Use two tables, one to model the Carousel, one to store image information, then link them.
Table Carousel:
id
[more fields here]
Table Image:
id
carousel_id (reference to the containing Carrousel)
[more fields]
I have to develop a shopping site where I need to maintain data like "Add to Cart" and "Previous Orders" for a single user, for N number of users in a database. E.g. if there is a user named "Mark" and I need to store his 5 items previously added to cart and 4 items as previous order and there are say 100 users like him whose data I need to store, How should I solve this problem? I am using PHP and MySQL.
Each user is assigned a unique ID (you can exploit MySQL's AUTO_INCREMENT for this purpose when creating the table of users.
Then, for items the users select, you create another table including the User_ID (from the previous table), the Item_ID (from a similar table for items), the status (that would indicate the status of the item for the specific user) and an optional field that would contain the order number when the user places the order (for one or more items).
In summary, and since you are actually asking for help in designing your database, I would suggest you sit with a pencil and a piece of paper and make lists of informational elements that you need, marking the one-to-one relation between them (when applicable). This will (approximately) suggest what needs to be arrange in a record of a table (e.g. all the stable details of a user would normally go together into a single table).
I have a MySQL database with a growing number of users and each user has a list of items they want and of items they have - and each user has a specific ID
The current database was created some time ago and it currently has each users with a specific row in a WANT or HAVE table with 50 columns per row with the user id as the primary key and each item WANT or HAVE has a specific id number.
this currently limits the addition of 50 items per user and greatly complicates searches and other functions with the databases
When redoing the database - would it be viable to instead simply create a 2 column WANT and HAVE table with each row having the user ID and the Item ID. That way there is no 'theoretical' limit to items per user.
Each time a member loads the profile page - a list of their want and have items will then be compiled using a simple SELECT WHERE ID = ##### statement from the have or want table
Furthermore i would need to make comparisons of user to user item lists, most common items, user with most items, complete user searches for items that one user wants and the other user has... - blah blah
The amount of users will range from 5000 - 20000
and each user averages about 15 - 20 items
will this be a viable MySQL structure or do i have to rethink my strategy?
Thanks alot for your help!
This will certainly be a viable structure in mysql. It can handle very large amounts of data. When you build it though, make sure that you put proper indexes on the user/item IDs so that the queries will return nice and quick.
This is called a one to many relationship in database terms.
Table1 holds:
userName | ID
Table2 holds:
userID | ItemID
You simply put as many rows into the second table as you want.
In your case, I would probably structure the tables as this:
users
id | userName | otherFieldsAsNeeded
items
userID | itemID | needWantID
This way, you can either have a simple lookup for needWantID - for example 1 for Need, 2 for Want. But later down the track, you can add 3 for wishlist for example.
Edit: just make sure that you aren't storing your item information in table items just store the user relationship to the item. Have all the item information in a table (itemDetails for example) which holds your descriptions, prices and whatever else you want.
I would recommend 2 tables, a Wants table and a Have table. Each table would have a user_id and product_id. I think this is the most normalized and gives you "unlimited" items per user.
Or, you could have one table with a user_id, product_id, and type ('WANT' or 'HAVE'). I would probably go with option 1.
As you mentioned in your question, yes, it would make much more sense to have a separate tables for WANTs and HAVEs. These tables could have an Id column which would relate the row to the user, and a column that actually dictates what the WANT or HAVE item is. This method would allow for much more room to expand.
It should be noted that if you have a lot of of these rows, you may need to increase the capacity of your server in order to maintain quick queries. If you have millions of rows, they will have a great deal of strain on the server (depending on your setup).
What you're theorizing is a very legitimate database structure. For a many to many relationship (which is what you want), the only way I've seen this done is to, like you say, have a relationships table with user_id and item_it as the columns. You could expand on it, but that's the basic idea.
This design is much more flexible and allows for the infinite items per user that you want.
In order to handle wants and have, you could create two tables or you could just use one and have a third column which would hold just one byte, indicating whether the user/item match is a want or a need. Depending on the specifics of your projects, either would be a viable option.
So, what you would end up with is at least the following tables:
Table: users
Cols:
user_id
any other user info
Table: relationships
Cols:
user_id
item_id
type (1 byte/boolean)
Table: items
Cols:
item_id
any other item info
Hope that helps!
I am building a database in MySQL that will be accessed by PHP scripts. I have a table that is the activity stream. This includes everything that goes on on the website (following of many different things, liking, upvoting etc.). From this activity stream I am going to run an algorithm for each user depending on their activity and display relevant activity. Should I create another table that stores the activity for each user once the algorithm has been run on the activity or should I run the algorithm on the activity table every time the user accesses the site?
UPDATE:(this is what is above except rephrased hopefully in an easier to understand way)
I have a database table called activity. This table creates a new row every time an action is performed by a user on the website.
Every time a user logs in I am going to run an algorithm on the new rows (since the users last login) in the table (activity) that apply to them. For example if the user is following a user who upvoted a post in the activity stream that post will be displayed when the user logs in. I want the ability for the user to be able to access previous content applying to them. Would it be easiest to create another table that saved the rows that have already been run over with the algorithm except attached to individual users names? (a row can apply to multiple different users)
I would start with a single table and appropriate indexes. Using a union statement, you can perform several queries (using different indexes) and then mash all the results together.
As an example, lets assume that you are friends with user 37, 42, and 56, and you are interested in basketball and knitting. And, lets assume you have an index on user_id and an index on subject. This query should be quite performant.
SELECT * FROM activity WHERE user_id IN (37, 42, 56)
UNION DISTINCT
SELECT * FROM activity WHERE subject IN ("basketball", "knitting")
ORDER BY created
LIMIT 50
I would recommend tracking your user specific activities in a separate table and then upon login you could show all user activities that relate to them more easily. ie. So if a user is say big into baseball and hockey you could retrieve that from their recent activity, then got to your everything activities table and grab relevant items from it.
Currently I have a form that submits an image with textfields such as
title, description and another field that autoincrements for imageID, another
area for the actual file , called vfile, and *** another part that has
3 checkboxes and a text field.
Everything works fine, and this is what it does. Submits the data to a database so that it can pull the information to a page on the website.
The only part I am trying to update is:
The 3 checkboxes and the textfield.
Lets say the first checkbox reads: Apples
The second : Oranges
The Third: Grapes
And in the other category is a blank textfield that if you add something, it would add it to a category called "Other".
So the database design has 4 fields: 1 - apples, 2 - oranges, 3 - grapes, 4 - other.
When I click a checkbox, it would add checked to the database under the correct one, either apples, oranges, or grapes.
If I add a field to the textbox such as: Bannanas, then it would add "Bannanas" to the database field vother and show that in the database.
This is all fine, but what if the next picture has all 4 items, plus another one? Such as if the next picture had Apples, Oranges, Grapes, Bannanas, and Plums?
How could I have the "Bannanas" other category, change into a checkbox category that could be chosen for the next pics when I go to the add images page next time.
So that when I go to the second picture to submit, it would give me the option of not just 3 checkboxes, but 4 checkboxes now, that I could check the first 4, "Apples, Oranges, Grapes, Bannanas" and then put Plums in the other category.
Basically upon submit it takes what is in the other feild and addes a new category to the database, which is then displayed in the array of checkbox choices and it is removed from the Other Category now, for it is a checkbox. (thus it would not want the value left in the old field, for it would keep creating the same category over and rewriting the old data possibly.
Anyway, any suggestions?
Thanks in advance.
(It sounds like this is more of a database design question and not a php question, but I may be misunderstanding what it is you are looking for advice on)
It sounds like you are saying that these attributes (Apples, Orange, etc) are stored as columns in your main table; but the situation you are describing sounds more like Tagging. Typically you would maintain a list of things that get tagged (your images), and a separate list of all possible tags (Which would be a table containing the rows : Apple, Orange, Grape). Your UI has the option to select from pre-existing tags (rows in the tag table) or add a new tag using the "Other" box. New tags would be added as a new row to the tag table. Since tags and tagged items have a many-to-many relationship you would create a third table (called a join table) that stores keys of tagged items and keys of tags; that way you can select either side of the relationship easily : get all the tags for a given item; get all the items with a given tag.
Does that help?
(EDIT : for comments)
So, Activities sounds like the list of Tags. If I want to show a form with checkboxes for all the Activities I can query the activities table for them. Each of those checkboxes can have a name attribute or something that captures the ID of the row that its bound to.
Also I would select from the join table the ids of the tags that my currently viewed image has selected. As I am populating the checkbox list I can check this result set to see if the id of the checkbox I'm putting on the page is in the list of tags for the image.
To store this back to the db on submit, the easiest thing is probably to (in a transaction) delete all the entries for the image from the join table and replace them with new entries based on the state of the check boxes in the form.
Drop the apples, oranges and grapes columns.
Create a second table with two fields: imageID and itemtype.
Don't make any of the two a key. Now you can list as many different types of items for each image as you need. It will be comparatively expensive to get the list of item types in use from the database but unless you have millions of items this shouldn't be a problem. (Mikeb is suggesting to keep the list of item types in use in a separate table to speed this up.)
The alternative is to dynamically add a column to the first table for each item type you encounter. This will create a very sparse table. I wouldn't do this.
You need to change your database schema to support an infinite number of attributes.
You should move your list of attributes from a set of fields in the record to a list of related records in a new table. This new table requires 2 columns. The first is the primary key from the existing table so you can establish the relationship between the tables. The second is the attribute field ('Bananas' or 'Apples' or 'Plums', etc.) You can have as many records in the attributes table as you like for each record in your main table. You could also have no attribute records if none are checked.
This kind of relationship between two tables is called a one-to-many relationship.