SQL query - Two tables with relation many to one (Normalization issue) - mysql

I have this example tables:
table ORDERS
client orderno cant1 code1 notes1 cant2 code2 notes2 cant[i] code[i] [...]
--------------------------------------------------------------------------------------
1 1 3 AA01 Test 4 BB01 Testing
2 2 10 XX05 Test
table PRODUCTS
code prod price
---------------------
AA01 Engine 100
BB01 Wheel 50
table CLIENTS
client name address telephone
-----------------------------------------
1 Maxwell 24 1st st 0987654321
2 Hammer 77 main st 1234567890
I need to relate them to get the quantity, name of the product and price for each of the product lines (they are 30 cant[i], code[i] and notes[i]) and the customer's information (name, address, etc)
I found this case, but I don't understand how to apply it to mine: SQL query two tables with relation one-to-many
I hope it's not too complex.
Thanks in advance!
EDIT
Thanks to ElectricLlama I realized the problem here is the table where the order is storaged. According to his answer, the normalization of the database would improve the way I'm able to get the info.
For anyone interested in this solution, I found this great website: http://www.devshed.com/c/a/MySQL/An-Introduction-to-Database-Normalization/
This SO answer clears it ALL! Super clear and understandable!
https://stackoverflow.com/a/1258776/888292

Looking at what's in your link - yes it seems like a lot of nonsense, but it is probably the only way to get what you want.
The problem is that your table is not normalised. Specifically you should not have fields called code1 code2 code3 code4... code30
There are many flaws with this design including what happens when a client has 31 products?
In a normalised database you would have a table with one set of cant, code and notes, and you would have one row per product.
But I guess you are not in a position to normalise it.
So well done for coming up with your own answer, and you now you also have first hand experience of the repercussions of not normalising a database.
What you might want to consider is creating a view that will normalise this for you. It will introduce performance issues but it will give you an introduction to views, and give you an opportunity to see how the solution would look like against a normalised table.

Ditto #ElectricLlama & here are a few links that should help you learn SQL:
W3Schools: SQL Tutorial
SQLServerCentral.com Stairway Series

I think that your table should be look like
Table orders
-------------
orderno
client
code
cant
note
Here make orderno, client and code make a composite primary key of the table

Related

Is there a way to add an attribute to only 1 row in SQL?

Take this table as an example :
CREATE TABLE UserServices (
ID BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
Service1 TEXT,
Service2 TEXT,
.
.
.
) ENGINE = MYISAM;
Every user will have different number of services, so lets say the table starts with 10 columns for services for each user. If one user will have 11 services, must all other users have 11 columns also? Now of course it is a table and row needs to have the same number of columns, but it is just seems like an awful waste of memory. Maybe the use of another database type is better?
Thank you!!
Storing a boatload of nulls isn't really a "waste of memory" because the space is negligible - hard disks cost pence per gigabyte, programmers cost tens/hundreds of $/hr so it's certainly economical to burn the space and it's not really a great argument for avoidance.
There is a better argument though, as others have said; databases don't do variable numbers of columns for a particular ID in a table, but they DO do variable numbers of rows per ID.. This is how DBs are designed: columns are fixed, rows are variable. Everything that a database does and offers in terms of querying, storage, retrieval, internal design etc is optimised towards this pattern
There are well established operations (called pivots) that will turn your vertical arrangement of data into horizontal (with nulls) at query time, so you don't have to store the data horizontally
Here's a pivot example:
Table:
ID, ServiceIdentifier, ServiceOwner
1, SV1, John
1, SV2, Sarah
2, SV1, Phil
2, SV2, John
2, SV3, Joe
3, SV2, Mark
SELECT
ID,
MAX(CASE WHEN ServiceIdentifier = 'SV1' THEN ServiceOwner END) as SV1_Owner,
MAX(CASE WHEN ServiceIdentifier = 'SV2' THEN ServiceOwner END) as SV2_Owner,
MAX(CASE WHEN ServiceIdentifier = 'SV3' THEN ServiceOwner END) as SV3_Owner
FROM
Table
GROUP BY
ID
Result:
ID SV1_Owner SV2_Owner SV3_Owner
1 John Sarah
2 Phil John Joe
3 Mark
As noted, it's not a huge cost to just store the data horizontally and if you're sure the table will never change/ not need new columns adding on a weekly basis to cope with new services etc, then it might be a sensible developer optimisation to just have columns full of nulls. If you'll add columns regularly, or one day have thousands of services, then vertical storage is going to have to be the way it goes
To expand a little on what's already been said:
Is there a way to add an attribute to only 1 row in SQL?
No, and that's kinda fundamental to how relationship databases (SQL) work - and that's in any version of SQL, whether it's mysql, t-sql, etc. If you have a table - and you want to add an attribute to that table, it's going to be another column, and that column will be there for every row. Not just relational databases - that's just how tables work.
But, that's not how anyone would do it. What you would do is what Alan suggested - a separate table for Services, then a 3rd table (he suggested naming it 'UserServices') that links the two. And that's not a one-off suggestion - that's pretty much "the" way to do it. There's no waste.
Maybe the use of another database type is better?
Possibly, if you want something with less restrictions, then you could go with something other than SQL. Since SQL is so dominant, everything is usually categorized as NOSQL. - Mongo is the most popular NOSQL database currently, which is why RC brought it up.

Does adding information to this table makes it lose its 3NF

The table below is from a tutorial where the tables are in 3rd normal form. But if I insert information into the table PROJECT as follows:
projectCode projectDescr customerNo
1 Apples 21
1 Apples 22
Didn't I lose the 3NF cos the projectcode and projectdescr ends up repeating since 2 customers could possibly have the same project?
So my question is whether the table in the image below is in 3NF. And does the above problem even exists or I am looking at it wrongly? I am setting up my own table but before that I am trying to get the 3NF understanding right. Please help. Thanks.
The table from the tutorial:
The assumption in the example would be that the relationship between PROJECT and CUSTOMER is many to one. A customer may have multiple projects but each project applies to only one customer. If you want a project to apply to multiple customers, then you need to split out another project_customer table that just contains a project and customer key for each row.

Ideas for stock management using mysql

I am creating a database for a publishing company. The company has around 1300 books and around 6-7 offices. Now i have created a table that displays the stock items in all locations. The table should look like following to the user:
Book Name Location1 Location2 Location3 ......
History 20000 3000 4354
Computers 4000 688 344
Maths 3046 300 0
...
I already have a Books table which stores all the details of the books, i also have a office table which has the office information. Now if i create a stock management table which shows the information like above i will end up in a huge table with a lot of repetition if i store my data in the following way:
Column1- Book_ID Column2- Location_ID Column3- Quantity
1 1 20000
1 2 3000
1 3 4354
2 1 4000
2 2 688
...
So, i think this isn't the best way to store data as it would end up with 1300 (Books) X 7 (Locations) = 9100 rows. Is there a better way of storing data. Now i can have 7 additional columns in the Books stable but if i create a new location, i will have to add another column to the Books table.
I would appreciate any advice or if you think that the above method is suitable or not.
Nope, that's the best way to do it.
What you have is a Many-to-Many relationship between Books and Locations. This is, in almost all cases, stored in the database as an "associative" table between the two main entities. In your case, you also have additional information about that association, namely, it's "stock" or "quantity" (or, if you think about it like a Graph, the magnitude of the connection, or edge-weight).
So, it might seem like you have a lot of "duplication", but you don't really. If you were to try to do it any other way, it would be much less flexible. For example, with the design you have now, it doesn't require any database schema change to add another thousand different books or another 20 locations.
If you were to try to put the book quantities inside the Locations table, or the Locations inside the Books table, it would require you to change the layout of the database, and then re-test any code that might be use it.
Thats the most common (and effective) solution. Most frameworks like Django, Modx and several others implement Many2Many relations via an intermediate table only, using foreign key relations.
Make sure you index your table properly.
ALTER TABLE stock_management add index (Book_ID), add index (Location_ID)
That really the best way to do it; you have 9100 independent data to store, so you really do need 9100 rows (less, really; the rows where the quantity is 0 can be omitted.) Other way of arranging the data would require the structure of the table to change when a location was added.

Database Design for Rental Listings

I'm designing a simple database for a rental listings website,
sort of like classified ads but only for home/room rentals. This is what I've come up with thus far:
Question 1
For the "post" table, I actually wanted more information. For example, there would be a 'facilities' section where the users can select whether there's 'parking' available, do I need a separate table? Or just use 0 for no and 1 for yes?
Question 2
Here's what I did with the "category" table (sorry I don't know how to pretty print yet)
Category_ID 1 is Rent
Category_ID 2 is buildingType
For "categoryProperty" table
Category_ID 1 categoryPropertyID 1 House
Category_ID 1 categoryPropertyID 2 Room
Category_ID 2 categoryPropertyID 3 Apartment
Category_ID 2 categoryPropertyID 4 Condominium
Category_ID 2 categoryPropertyID 5 Detached
Does the above make sense?
Question 3
Users can post whether they are logged in or not. Just that logged in users/members have the advantage of tracking their ads/adjusting the availability.
How do I record the ads that a member has posted? Like their history.
Should I create a "postHistory" table and set the 'postHistory_ID' as FK to "member" table?
Thanks a lot in advance, I appreciate your help, especially just pointing me to the right direction.
Question 1:
make a separate table and make a One to One relation, that would be the simplest way:
POST -|-----|- EXTRAS
in EXTRAS you may have every extra field (parking=1/0, in_down_town=1/0,has_a_gost=1/0)
Question 2:
This does not make sense, you've two options:
in the Post table create a "type_of_operation", that can have two vales (building_type,rent). Or you can create different tables, but would make this more complicate (you should analyise if the same type can be in both states, etc).
Question 3:
I recommend you to make your users register. Even with a really simple form (email+password) .
Seems to be on the right track -- with respect to your specific questions:
Question #1: Assuming there's more than one type of facility (parking; swimming pool; gym) then you have a many-to-many relationship and you want 2 new tables: Facilities and PropertyFacilities. Each Property (or I guess "post") could have multiple rows in the PropertyFacilities table.
Question #2: Not really clear on what you're getting at -- is it that each property type can either be rented whole or rented per room?
Question #3: Good question, what you want to do is have an Active bit, or an ExpireDate, in your POST table -- then anything that becomes inactive or expired is automatically 'historical' data, no need to marshall it to a history table. Although you'll have to archive eventually of course.

Associating extra data with a MySQL column

I have a typical table, e.g.
id(int) name(varchar) address(varchar) date(datetime)
I also have a table that references validation functions for each one, e.g.
id(int) function(varchar) fail_message(varchar)
1 email Please enter a valid email address
2 required This field can not be left blank
I'd like to be able to associate each column from the first table with one or more of these validators.
The only way I can think of doing this is to stuff the ids into the column names e.g. (column name: email;1;2) and keep track of it through PHP, but that seems very messy.
Is there a good way to do this with relational databases? Would a NoSQL implementation suit this problem better?
Similar to what Dan said, a relatively easy way to implement an association in sql would be to do the following:
id(int) function_id(int) col_name(varchar)
1 1 address
2 1 second_address
3 2 address
4 2 name
And then when you want to do the failure check, use the above table to link the error message to the column name (e.g. 'select function_id from above_table where col_name="address"') and then query the failure table. These tables could subsequently be combined using a view with a join so that a single query would suffice.
Hope this helps.
put this in another table that describes the columns for tables oddly this is very much like extending the table that lists table columns with additional columns
let's say if you extend your example with say localized strings that would mean that the fail_message would become a fail_message_id and the table fail_message would have the columns (id, language, message)