Should I reference a field id or have the actual data in the same row? - mysql

I have two tables, meetings_table and items_table.
items_table has three columns:
id
item
description
meetings_table has two columns:
first_party
second_party
I want to show the names of the two parties and the item they're meeting about. Should I add another column to meetings_table referencing the id of the item in items_table, then pull the item's name and description from there? Or should I add two columns to meetings_table, item and description and just run one query that way? Which is best in principal efficiency?

You should just reference the id of the item. This way, if you need to update anything about the item, you just do it in one location and it will propagate across all queries using that data. You almost never want to store data twice in a database. Every once in awhile you will come across a situation where unnormalized data is acceptable, but this is the exception, not the rule.

The best thing to do is to have an id for each item and add the id to the meetings_table, and query from there like
SELECT * FROM meetings_table a, items_table b WHERE a.item_id=b.item_id
This will make item and meetings kinda independent of one another, and also saves space.

Related

The best/correct way in MySql to group records (not "Group By")

I have a table that is going to have a bunch of stock numbers and some other information. I need to be able to create groups of stock numbers e.g. products 123A,456B, and 789C all are in the same group. Each stock number has its own record in the table. I don't really care how it is accomplished so long as I can make sure that the items are grouped and that group numbers are unique. What is the best way to accomplish this?
There are a few ways I can think of to accomplish this but I'm not really sure what the best way is or if there are hidden drawbacks:
1) I could have a separate table with one auto increment column that is responsible for generating group id's and then add the Id to the stock number table once it's generated but that semes wasteful.
2) Would selecting the max groupId from the stock number table and adding one to it be good to get new group id's?
3) I could not have groupId in the stock number table and do it using a separate table with a GroupID column and a StockNumberId column. Still how would I get the groupId doing it this way?
You don't have to respond to all three. In indication of which would be the most appropriate way and any notes on implementation or pitfalls would be helpful. Also if there is a better way I did not innumerate please enlighten me. Thank you.
If you only need to set a groupId for each stock, and if each stock belongs to one and only one group then solution (2) would work just fine.
I would also create an index on the groupId column for easy retrieval of stocks that belong to the same group, as well as for getting the MAX(groupId) more efficiently.
I would use solution (1) if I had to also store group information, e.g., groupName, etc.
Solution (3) would be more towards a Many-To-Many relation between Stocks and Groups where the table you are describing sits in between the two. But in your case this would not be a good solution.

Best way to make favoruites/related content in tables?

I'm looking for a good way say, to save favorite images for a specific user in the database. Or if I have a movie, I want to display related movies, you get the idea. I don't know how to do it on a database level (phpmyadmin). My idea so far is if I have a table named Users, I add a column in it named Favorites, in which I enter every ID or Name of the favorite item. The problem is that the content in this column may grow a lot more than I expect, and I don't feel this is a good way to do it. So how do I go about this?
Try having a table called "Favourites" with a column called UserID and another column for the ID or name of the favourited items. Then you would have one row for each user/favourite pair.
This allows you to have many favourites per user, and you can maintain arbitrary metadata about each favourited item (for example the time and which it was selected as the favourite).
You can also answer questions like "Which users have favourited a given item?" with this approach.
This is standard DB modelling for this type of problem.

MySQL table with multiple values in one field [duplicate]

This question already has answers here:
Is storing a delimited list in a database column really that bad?
(10 answers)
Closed 4 years ago.
I'm building a database for a real estate company.. Those real estate properties are managed by the sales people using a CodeIgniter website.
How should I proceed with the database design for this table. The fields like address/location, price etc. are pretty straightforward but there are some sections like Kitchen Appliences, Property Usage etc... where the sales people can check multiple values for that field.
Furthermore, a property can have multiple people attached to it (from the table people), this can be an intermediaire, owner, seller, property lawyer etc... Should I use one field for this or just I create an extra table and normalize the bindings?
Is the best way to proceed just using one field and using serialized data or is there a better way for this?
In a relational database you should never, EVER, put more than one value in a single field - this violates first normal form.
With the sections like Kitchen Appliances, Property Usage etc... where the sales people can check multiple values for that field, it depends on whether it will always be the same set of multiple options that can be specified:
If there are always the same set of multiple options, you could include a boolean column on the property table for each of the options.
If there are likely to be a variety of different options applicable to different properties, it makes more sense to set up a separate table to hold the available options, and a link table to hold which options apply to which properties.
The first approach is simpler and can be expected to perform faster, while the latter approach is more flexible.
A similar consideration applies to the people associated with each house; however, given that a single property can have (for example) more than one owner, the second approach seems like the only one viable. I therefore suggest separate tables to hold people details (name, phone number, etc) and people roles (such as owner, seller, etc.) and a link table to link roles to properties and people.
You should create extra table for it....
For example...
Consider the scenario that 1 item may have many categories and 1 category may have many items...
Then you can create table like this...
Create three tables for that....
(1) tblItem :
fields:
itemId (PK)
itemName
etc..
(2) tblCategory :
fields:
categoryId (PK)
categoryName
etc..
(3) tblItemCategory :
fields:
itemId (PK/FK)
categoryId (PK/FK)
So according to your data you can create an extra table for it....
I think it would be optimize way....
If you want your data to be in third normal form, then you should think in terms of adding extra tables, rather than encoding multiple values into various fields. However it depends how far your brief goes.

Merge two results in a MySQL query if the records are related by a field value

We have a products table. Users can create new products as copies of existing products.
Instead of simply duplicating this data, we're thinking in order to minimize database size, we would store only the differences from the "parent" product. (were talking thousands of products)
My thinking is that, for each new "child" product, we create a new record in that same table which has a "parent" field which has the ID of the parent product.
So, when querying for the "child" product, is there a way to merge the results so that any empty fields in the child record will be taken from the parent?
(I hope this makes sense)
Yes, you can do this.
Say for example Your table name is Product and you want to retrieve name of child product, Then you can query as,
select IF(c.productName = '',p.productName,c.productName) as childProductName
from Products p,Products c
where c.ID = p.ParentID
Similarly you can do this for other fields.
I would anticipate that you'd want to have child products of child products (e.g. product C is based on product B, which is in turn based on product A.) And there would be children of those and so on (especially with user generated content.) This could get out of hand very quickly and require you to make either long cumbersome queries or collect the data with code rather than SQL queries.
I'm just offering this as a consideration because the saving is size often yield a cost of processing time. Just be sure you consider this before you jump into something that can't easily be undone.

MySQL, per found record join a different parent table

I have the following parent <-> child datamodel:
(almost every line is a table, indented means child-of)
consumerGoods
food
meat
item
fruit
item
vegetable
item
The child-items of meat, fruit and vegetables are in the same table (named items) because they have identical attributes. In the items table I have fields that describes the parent and the parentId.
So an item record could be:
id:1
parentType:meat
parentId:4
price:3.25
expDate:2009-12-31
description:bacon
I'm now building a full text MySQL search for the contents of the description field in "items", but I also want each result to have the information of its parent table, so a "bacon-item" has the data that's in its parent record. I also want each returned result to have data that is in the parent food record and the parent consumerGoods record.
I've got the following query now, but I don't know how to join based on the value of a field in a record, or if that's even possible.
SELECT
*
FROM
item
WHERE MATCH
(description
AGAINST
('searchKey')
One way to do this is is to do multiple queries for each matching "item" record, but if I had a lot of results that would be a lot of queries and would also slow down any filtering I'd want to do for facet-based searching. Another option is to make a new table that contains all the parent item info for each item record and search through that, but then I'd have to constantly update that table if I add item records, which is redundant and quite some work.
I'd like to hear it if I'm thinking in the right direction, or if I'm totally misguided. Any suggestions welcome.
As a general rule of thumb your database structure should contain data, but should not itself be data. A sign that you're breaking this is when you feel that you have to join to a different table based on the data you're reading from some other table. At that point you need to back up and consider your overall data model because odds are very good that you're doing something not quite right.
You could join against a subquery containing the union of all parent types:
select *
from item
left join (
select 'meat' as type, Redness, '' as Ripeness from meat
union all
select 'fruit' as type, -1 as Redness, Ripeness from fruit
union all
select 'vegetable' as type, -1 as Redness, Ripeness from vegetable
) parent on parent.type = item.parentType
But if you can, redesign the database. Instead of the complex model, change it to one table of Items and one table of Categories. The categories should contain one row for meat, one for fruit, and one for vegetables.
Since your example is contrived, it's difficult to know what the actual information requirements are in your case. Damir's diagram shows you the correct way to model PKs and FKs when you have a super-type sub-type relationships.
This situation is one case of a pattern called "generalization-specialization". Almost any treatment of object modeling will deal with generalization-specialization, although it may use different terminology. However, if you want to find articles that help you build a relational database that uses specialization-generalization, search for "generalization specialization relational modeling".
The best of the articles will start by teaching you the same concept that Damir's response illustrated for you. From there, you will learn how to create queries and views that can search for either all kinds of items, or for particular kinds of items, if you know what you are searching for.
A sample view follows:
create view FruitItems as
select
c.ConsumerGoodsID,
Price,
Description,
ConsumerGoodType,
ExpiryDate,
FoodType,
IsTropic
from
ConsumerGoods c
INNER JOIN Food f on f.ConsumerGoodsID = c.ConsumerGoodsID
INNER JOIN Fruit fr on fr.ConsumerGoodsID = c.ConsumerGoodsID
Similarly, you could create views for VegetableItems, MeatItems, and HouseSupplyItems, and even one large view, namely Items, that's the union of each of the specialized views.
In the Items view IsTropic would be true for all tropical fruits, false for all non tropical fruits, and null for Meats, Vegetables, and HouseSupplies. I'm not going to show you the entire Item view for a contrived case, but you get the idea. Especially if you read the best of the articles on relational modeling of this pattern.
The Items view might be a little slow, but it could come in handy when you really don't know any better way to search. And if you search for Istropic = True, you'll automatically exclude all the Meats, Vegetables, and HouseSupplies.
As #Andomar suggested, the design is a bit off; having "multiple parent tables" does not map to DB foreign keys concept. Here is one possible suggestion. This one uses two levels of super-type/subtype relationships. Super-type table contains columns specific to all subtypes (categories), while subtype tables contain columns specific only to the category.