I have 14 tables (one for every year) with product code, firm name and invoice numbers. Main structure of table is identical (product code, ID), but there can be some variables in names of firms.
Table2011
| ID | productcode | firm1 | firm2 | firm3 | etc |
| 1 | G-00001 | 2;5;40| 32;67 | | 150 |
| 2 | G-00005 | | 50 | | |
|etc | | | | | |
Table2010
| ID | productcode | firm1 | firm2 | firm3 |etc |
| 1 | G-00001 | 1;10 | | 55 | |
| 2 | G-00003 | | 2 | | |
| 3 | G-00005 | | 50 | 40 | |
| etc| | | | | |
Table2009
...
Column Firm1 do not usually equals to same firm as firm 1 in other table
I am using table editor to work with tables (adding columns to table, editing values…).
I would like to know if it is possible to achieve result like below. It is above my PHP skills.
Product G-00001 page
…
<UL>
<LI>Year 2011: 150etc; 67firm2; 40firm1; 32firm2; 5firm1; 2firm1</LI>
<LI>Year 2010: 55firm3; 10firm1; 1firm1</LI>
<LI>Year 2009: ...</LI>
...
</UL>
…
Lemme begin with book recommendation : SQL Antipatterns. You will need it, doesn't matter if you caused this mess or ar just assigned to fix it.
If i was in your place, first thing would do would be to fix the database structure. This is madness. You do not need a new table for each year and new column for each company. Database is not a form of Excel spreadsheet.
Invoices Years Companies
----------------- ------------- ---------------
| product_code PK | | year_id PK | | company_id PK |
| company_id FK | | number | | title |
| amount | ------------- ---------------
| year_id FK |
-----------------
Where PK - primary key and FK - foreign key.
This structure would make the gathering of information much much much MUCH easier.
If you just want to display the data and not worry about the restructuring just yet you can use a JOIN to display the information from all the tables.
Although I would agree with teresko you really need to redesign that database. It is not maintainable the way it is.
Related
I have a small database:
+-----------+-----------+------------------------+
| Name | Number | Hobby |
+-----------+-----------+------------------------+
| Alex | 2, 3 | Game, Shopping |
+-----------+------------------------------------+
It's mean Number 2 is Game and Number 3 is Shopping.
How can I show above data like this table
+-----------+-----------+
| 2 | Game |
+-----------+-----------+
| 3 | Shopping |
+-----------+------------
Your database is not normalized. You need a third table that will be what's usually called a join table.
The people table. The primary key is id
+-----------+-----------+
| Id | Name |
+-----------+-----------+
| 1 | Alex |
| 2 | Thor |
| 3 | Iron Man |
| 4 | Dr Stange |
| 5 | Thanos |
+-----------+------------
The hobbies Table
+-----------+-----------+
| Id | Name |
+-----------+-----------+
| 1 | Game |
| 2 | Shopping |
| 3 | Fighting |
+-----------+-----------+
Join table called (for example) people_hobbies
+-----------+-----------+
| person_id | hobby_id |
+-----------+-----------+
| 1 | 1 |
| 1 | 2 |
+-----------+-----------+
This people_hobbies table will use person_id and hobby_id to create a multi field primary key. This will ensure that you will not be able to add the same combination twice... which should not even make sense.
person_id is a foreign key that references the id from the people table.
hobby_id is a foreign key that references the id from the hobbies table.
Having foreign keys will let you avoid having a key in the people_hobbies table that do not exist in both the people and the hobbies table.
The example in the table below shows that the person id 1 has two hobbies (1 and 2). For a human, that translates to Alex's hobbies are Game and Shopping.
The above structure will let you manage your DB the way most people do.
Just keep a few things in mind:
You cannot add anything in people_hobbies before they exist in both people and hobbies tables
You must have the CASCADE UPDATE and CASCADE DELETE to the foreign key definitions so that when you delete a person or a hobby from your tables, it will remove the relationship from the people_hobbies table.
SELECT * FROM ints;
+---+
| i |
+---+
| 0 |
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
+---+
SELECT * FROM bad_schema;
+------+--------+----------------+
| name | number | hobby |
+------+--------+----------------+
| Alex | 2, 3 | Game, Shopping |
+------+--------+----------------+
CREATE TABLE better_schema AS
SELECT DISTINCT name
, SUBSTRING_INDEX(SUBSTRING_INDEX(number,',',i+1),',',-1) + 0 number
, TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(hobby,',',i+1),',',-1)) hobby
FROM bad_schema
, ints;
SELECT * FROM better_schema;
+------+--------+----------+
| name | number | hobby |
+------+--------+----------+
| Alex | 2 | Game |
| Alex | 3 | Shopping |
+------+--------+----------+
I've got a small CRM and I'm trying to figure out the best way to designing the DB tables.
I've currently got a single table for users that got around 30 columns which I alter from time to time. Since I am storing two different information on that table (user + company information) I was thinking of splitting that table into 3 (user + company + connection between these 2) but I am also interested in keeping a copy of any changes that are being made in these rows.
So going from:
user_id | firstname | last_name | company_name | company_city | company_subject | rank | status
1 | John | Borrows | Boink INC | NY | Web dev | 1 | 1
2 | Mike | Smith | Smithin INC | OC | Laywer | 1 | 2
3 | Mary | Anton | Caffin | SJ | Moving | 2 | 1
to something like this
user_id | firstname | last_name | rank | status
1 | John | Borrows | 1 | 1
2 | Mike | Smith | 1 | 2
3 | Mary | Anton | 2 | 1
comp_id | company_name | company_city | company_subject
1 | Boink INC | NY | Web dev
2 | Smithin INC | OC | Laywer
3 | Caffin | SJ | Moving
con_id | user_id | comp_id
1 | 1 | 1
2 | 2 | 2
3 | 3 | 3
But I'm not sure how to track the changes when for example a user changes the company name or some other info on user's table etc.
Just follow the normalization rules for structuring your database tables. You will find anything you need for that by just searching for database normalization.
Regarding your "update-history" you could add a Timestamp to your datasets and/or a separate boolean field "outdated" to be able to filter out the latest information.
Would be the simplest solution that comes into my mind.
Category Table
+----+-----------------------+
| id | category_name |
+----+-----------------------+
| 1 | Buy Book |
| 2 | Buy other thinks |
+----+-----------------------+
Buy Table
+----+-----------------------+----------+-------------+----------+--------+-------+
| id | identity | name | description | per_rate | bought | costs |
+----+-----------------------+----------+-------------+----------+--------+-------+
| 1 | PROJECT[1]CATEGORY[1] | BOOK | PHP BOOK | 10 | 50 | 5000 |
| 2 | PROJECT[1]CATEGORY[1] | BOOK | PHP BOOK | 10 | 40 | 4000 |
| 3 | PROJECT[2]CATEGORY[1] | BOOK | JS BOOK | 2 | 50 | 100 |
+----+-----------------------+----------+-------------+----------+--------+-------+
I Want to Select category name from Other table when I select this table.
identity: PROJECT[project_id]CATEGORY[category_id]
So There are any way to pick the category id and select category name from other table
I Want Like This Table
+----+---------------+-----------------------+----------+-------------+----------+--------+-------+
| id | category_name | identity | name | description | per_rate | bought | costs |
+----+---------------+-----------------------+----------+-------------+----------+--------+-------+
| 1 | Buy Book | PROJECT[1]CATEGORY[1] | BOOK | PHP BOOK | 10 | 50 | 5000 |
| 2 | Buy Book | PROJECT[1]CATEGORY[1] | BOOK | PHP BOOK | 10 | 40 | 4000 |
| 3 | Buy Book | PROJECT[2]CATEGORY[1] | BOOK | JS BOOK | 2 | 50 | 100 |
+----+---------------+-----------------------+----------+-------------+----------+--------+-------+
You have a really bad data structure. The project and category should be in their own columns, with numbers stored properly as numbers, and proper foreign key relationships. In MySQL, doing this might require a trigger, but it is worth it.
Sometimes, we are stuck with other people's bad decisions. You can do what you want using like:
select b.*, c.category_name
from buy b join
category c
on b.identity like concat('%CATEGORY[', c.id, ']');
However, you should probably put effort into fixing the broken data structure.
I want to know if i'm setting up this database schema the most effective way.
I am trying to output snowboarding terminology and what it means for each product on my website. The tables that I have set up for this:
products
+----+--------+--------+-------------+
| id | brand | name | product_type|
+----+--------+--------+-------------+
|8000| burton | diode | binding |
+----+--------+--------+-------------+
terminology_products
+----+--------+------------+
| id | att_id | product_id |
+----+--------+------------+
| 1 | 51 | 8000 |
| 2 | 52 | 8000 |
+----+--------+------------+
terminology
+--------+-----------+--------+---------------------+
| att_id | type | key | value |
+--------+-----------+--------+---------------------+
| 52 | baseplate | EST | details about EST |
| 53 | baseplate | Hinge | details about Hinge |
+--------+-----------+--------+---------------------+
Then I query
SELECT products.ProductName, products.Brand, terminology.type, terminology.key, terminology.value
FROM products
JOIN terminology_products
ON terminology_products.product_id = products.ID
JOIN terminology
ON terminology_products.att_id = terminology.att_id
WHERE products.id = 8000
And get the results that I am looking for, but I feel like this could be an over complicated way of doing it. Is there a simpler way? Thank you for any insight or help.
Yes, it is a correct way. It's common solution.
Your "terminology_products" table contains foreign keys, and it allows you to make "many to many" relation between tables.
i have a table in following format:
id | title
---+----------------------------
1 | php jobs, usa
3 | usa, php, jobs
4 | ca, mysql developer
5 | developer
i want to get the most popular keywords in title field, please guide.
If you have a list of keywords, you can do the following:
select kw.keyword, count(*)
from t cross join
keywords kw
on concat(', ', t.title, ',') like concat(', ', kw.keyword, ',')
As others have mentioned, though, you have a non-relational database design. The keywords in the title should be stored in separate rows, rather than as a comma separated list.
If your data is small (a few hundred thousand rows or less), you can put it into Excel, use the text-to-columns function, rearrange the keywords, and create a new, better table in the database.
SELECT title 1, COUNT(*) FROM table GROUP BY title 1
EDIT
Since you've edited and presented a non-normalized table, I would recommend you normalize it.
Have a read of: http://blog.fedecarg.com/2009/02/22/mysql-split-string-function/
You need to modify your database. You should have something like this:
items
+----+---------------+
| id | title |
+----+---------------+
| 1 | something |
| 3 | another thing |
| 4 | yet another |
| 5 | one last one |
+----+---------------+
keywords
+----+-----------------+
| id | keyword |
+----+-----------------+
| 1 | php jobs |
| 2 | usa |
| 3 | php |
| 4 | jobs |
| 5 | ca |
| 6 | mysql developer |
| 7 | developer |
+----+-----------------+
items_to_keywords
+---------+------------+
| item_id | keyword_id |
+---------+------------+
| 1 | 1 |
| 1 | 2 |
| 3 | 2 |
| 3 | 3 |
| 3 | 4 |
| 4 | 5 |
| 4 | 6 |
| 5 | 7 |
+---------+------------+
Do you see the advantage? The ability to make relations is what you should be leveraging here.