I'm trying to setup groups in my network using MySQL. Users could join in groups or create groups. Of the two options below, I'm trying to identify which solution is better.
First Solution:
I create a Table called "Groups" with columns:
- GroupID
- GroupName
- Createtime
- GroupMembers...
In this solution I would save the users in the column GroupMembers like this "user1;/user2;/" and so on. This is my first solution; I don't know if this would be faster than the second solution. I just want to lookup GroupMembers, etc.
Second Solution:
I would create a table like in the first solution, but without the column GroupMembers, and I would create a second table for the GroupMembers.
This table will have following columns:
-GroupID //The ID of the group in the other table.
-UserID
When joins a group, it will be stored in the above table.
The first solution is Bad because it breaks normalization.
The second solution is Good.
The typical approach would be to have a Users table, a Groups table and a UserGroups (or GroupUsers) table
Related
I have two tables:
One table is called item, which among other things contains item_name.
The second table that I have is called recipe, which has 4 rows: recipe_id, item_id, nom_netto and tolerance.
Is there a way to temporarily show the item_name column in the recipe table?
If not temporarily, how would I go about to do it permanently?
Thanks in advance.
You can do that by using INNER JOIN.
Please see this example: https://www.w3schools.com/sql/sql_join_inner.asp
Please also see this to understand how different types of JOINS work: https://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins
I have two tables that have different data that I need to merge. They do have similarities such as: Order number, Name, type or product. But they have separate data as well like: Order date, and Engravings.
Would I do two separate Append queries in Access into a merged table? Or one Append queries? Or just keep the data separate?
I am new to Access and trying to find the best way to approach this.
Merging the two tables into one completely defeats the purpose of using a database and you're better off using excel at that point. You want to split the data as much as possible along logical lines so that you can find, say... all the orders that Mr X has ever made for a specific product. And in that case you're going to want to have separate tables for customers, orders, engravings and the like.
The best practice from a design standpoint is to place fields that each table has in common into a third "master" table, then create relationships from that table to the existing tables and delete the data that has been transferred to the main table (except for the primary keys, which have to be common with your master table).
To create the master table, use a Make Table query to generate the master table based on one of your tables, then an append query to add any products in the master table that might not be common to both, based on the other table. Finally, delete queries for each table would rid you of redundant data in both original tables.
However, I strongly suggest you use Microsoft's tutorials and download the NorthWind sample database so you can get an idea of what a properly structured database looks like. The beginner's learning curve for access is very steep and having well built example databases is almost a requisite.
Make a backup of your database(s) and play with it until it turns out right. Do not make the mistake of playing with live data until you know what you're doing.
As you have similar fields on either table, take the Order number field from both tables using a union query. Something like:
SELECT tbl_Delivery_Details.OrderNo
FROM tbl_Delivery_Details
GROUP BY tbl_Delivery_Details.OrderNo
UNION
SELECT tbl_Delivery_Header.[Order number]
FROM tbl_Delivery_Header
GROUP BY tbl_Delivery_Header.[Order number];
This would take the order numbers from the delivery details table and from the delivery header table and merge them into one list with only one instance of each order number. Save the query.
You could then use this query in a new query. Bring in your 2 tables to this query and insert the fields from either table that you require.
As users add records to the tables they will be added to the union selet query when it is next run.
PB
It depends on what you want to do. Let's assume you have tables A (with 50 records) and B (with 75) records, and both tables have a similar column called OrderID.
Appending Rows:
If you want to create a table with 125 total records by combining records (rows) from A and records (rows) from B, run the following two queries:
Query 1:
SELECT A.ORDER_NUMBER, A.TEXT_FIELD1 as DATA INTO C
FROM A;
Query 2:
INSERT INTO C ( ORDER_NUMBER, DATA )
SELECT B.ORDER_NUMBER, B.TEXT_FIELD2
FROM B;
Appending Columns: If you want to create a table with 75 total records where you are appending columns from A to the columns in B, then run the following query:
SELECT B.ORDER_NUMBER, A.TEXT_FIELD1, B.TEXT_FIELD2 INTO C
FROM A RIGHT JOIN B ON A.ORDER_NUMBER = B.ORDER_NUMBER;
... in a similar way, you can append columns in B to columns in A in a new table C with a total of 50 records by running the following query:
SELECT A.ORDER_NUMBER, A.TEXT_FIELD1, B.TEXT_FIELD2 INTO C
FROM A LEFT JOIN B ON A.ORDER_NUMBER = B.ORDER_NUMBER;
Lets consider three tables :
1.Companies
id
company_name
...
2. Employees
id
employee_name
...
3. Payment
id
pay_by
pay_to
...
Now the problem is here pay_to can be id of a Company or an Employee (fk). So I have added a Boolean column "is_company" in the Payment Table. So my solution is if is_company is True then its Company otherwise its Employee.
But I am not satisfied with this solution. I mean I don't want to have a column which has multi table foreign key. I think there has a better solution but I could not find that. Please help to find a better solution. Thanks in advance.
You could, depending on what you using to interact with the database, prefix the pay_to with a letter, e for employee or c for company however then you can't specify that the field is an int etc which may cause issues.
One alternative is to use different ranges (this would obviously limit the number of each you could have) but you could say 0-9999999 is employees and 10000000+ is company ID's.
Another alternative would be to have an interim table (called payees for example) where pay_to references a row in that table which gives you a payee type and then the payee's ID in their respective table.
--EDIT--
You could create a table called payees with columns such as payee_id, payee_type, id. payee_id would be an auto increment column that you would then reference in the payment.pay_to field. payee_type would be company/employee and then id would either be company.id or employee.id depending on the type. It would mean using 2 queries rather than using a join but that is true with any of the possibilites unless you could combine companies and employees in to one table - this would depend on the other columns beyond what you have detailed in your original question.
None of them are necessarily elegant (and there may and probably are other) solutions, but they would be the 3 I would look at using in your situation!
to build on what Ed Wade said, you could prefix all companies with a 1 and all employees with a 2. This would help with keeping the field as an integer while not limiting the number you could store
I am developing web application where I have to implement 'Likes' system as facebook has. Application will have a few categories of products that customer can 'like'. So I have started to create database, but I stuck on one obstacle. As I understand there are two ways of doing this:
First. Create one database table with fields of "id, user_id, item_category, item_id". When user click 'like' button information will be saved in this table with various categories of products (item_category).
Second. Create several tables for certain categories of item. For instance, "tbl_item_category_1, tbl_item_category_2, tbl_item_category_3" with fields of "user_id, item_id".
Would be great to get more insight about best practices of this kind database structures. Which works faster? and more logical/practical? I will use only several categories of items.
I would go with the first version with a table structure similar to this:
User Table: PK id
id
username
Category Table: PK id
id
categoryname
Like Table: PK both user_id and catgory_id
user_id
category_id
Here is a SQL Fiddle with demo of table structure with two sample queries to give the Total Likes by user and Total Likes by category
The second one - creating multiple tables is a terrible idea. If you have 50-100 categories trying to query those tables would be horrible. It would become completely unmanageable.
If you have multiple tables trying to get a the total likes would be:
Select count(*)
from category_1
JOIN category_2
ON userid = userid
join category_3
ON userid = userid
join .....
Use one table, no question.
The first method is the correct one. Never make multiple tables for item categories, it makes maintaining your code a nightmare, and makes queries ugly.
In fact, the general rule is that anything that is dynamic (i.e. it changes) should not be stored as a set of static objects (e.g. tables). If you think you might add a new type of 'something' later on, then you need a 'something' types table.
For example, imagine trying to get a count of how many items a user has liked. With the first method, you can just do SELECT COUNT(*) FROM likes WHERE user_id = 123, but in the second method you'd need to do a JOIN or UNION, which is bad for performance and bad for maintainability.
The first method is the correct one. Because you dont know how many categories you will be having and it is very difficult to get the data.
Is there any way how to create an functioning index for this query and to get rid of "filesort"?
SELECT id, title FROM recipes use index (topcat) where
(topcat='$cid' or topcat2='$cid' or topcat3='$cid')
and approved='1' ORDER BY id DESC limit 0,10;
I created index "topcat" ( columns: topcat1+topcat2+topcat3+approved+id) but still ge "Using where; Using filesort".
I can create one more column, lets say, "all_topcats" to store topcat numbers in an array - 1,5,7 and then to run query "... where $cid iIN ()...". But the probem is that in this case "all_topcats" column will be "varchar" but "approved" and "id" columns - int, and index will not be used anyway.
Any ideas? Thanks.
You might improve performance for that query if you reordered the columns in the index:
approved, topcat1, topcat2, topcat3, id
It would be useful to know what the table looks like and why you have three columns named like that. It might be easier to organise a good query if you had a subsidiary table to store the topcat values, with a link back to the main table, but without knowing why you have it set up like that it's hard to know whether that would be sensible.
Can you post the CREATE TABLE?
Edit in response to user message
Your table doesn't sound like it's well-designed. The following design would be better: Add two new tables, Category and Category_Recipe (a cross-referencing table). Category will contain a list of your categories and Category_Recipe will contain two columns, one a foreign key to Category and one a foreign key to the existing Recipe table. A row of Category_Recipe is a statement "this recipe is in this category". You will then be able to very simply write a query that will search for recipes in a given category. You also have the ability to put a recipe in arbitrarily many categories, rather than being limited to 3. Look up "database normalisation" and "foreign keys".