I have a table in Mysql that looks like this:
Name Slot_1 Slot_2 Slot_3
------ ------ ------ --------
MyName MyItem
MyName2
And I have this app with an interface to buy some products. When the client "MyName" buy something in the app, it would store it on "Slot_2" because "Slot_1" is already used; On the other hand, if MyName2 buys the same product, it would be stored on Slot_1 because it's the first free slot found. I searched through several links, but all I found was how to update the first empty row found, and not the column.
Note: The app is made in VB.net, so if you think it would be better to do this app-level, feel free to comment.
Note 2: This is the best db-design I found to do this "inventory". If you think there is a better way to do it, please point me to it.
That is really a bad design. I really suggest to read something basic on building relational databases.
Said that the only correct approach is to have at least three tables
The first table contains the customer informations
IDCustomer Name Address City
---------- ------ ------ --------
1 Steve XXXX YYYY
2 Andre KKKK ZZZZ
The second table contains the Items that can be sold
IDItem Item Price
---------- ------ ------
1 Apple 1
2 Orange 2
The third table links the Customers with the Items sold
IDItem IDCustomer Quantity
------- ----------- ---------
1 1 5
2 2 10
1 2 3
Also if you want to limit the items sold to a customer to only three, that is a business rule that should not be enforced by a database design like that.
Related
This question already has answers here:
Is storing a delimited list in a database column really that bad?
(10 answers)
Closed 3 years ago.
This is the table of database
**
id products free_pro_id
1 laptop 2
2 pen-drive -
3 hard-disk 2,4
4 mouse 3
i am just wondering how to create query for below output
product free_id_pro**
laptop pen-drive
hard-disk pen-drive,mouse
mouse hard-disk
I understand your problem. But your table implementation is not correct.
First, you have to learn about Database Normalization.
Please refer to this link
https://www.studytonight.com/dbms/database-normalization.php
You can have a table for products and another table for promotions.
Table Products
In this table you can have the prodId and the prodName
prodId-------prodName
1--------------laptop
2--------------pen_drive
3--------------hard_disk
4--------------mouse
Table Promotion
In this table, you can store what are the free products you are giving when user buys a product.
promoId--prodId----freeProdId
1-------------1------------2
2-------------3------------2
3-------------3------------4
4-------------4------------3
If you want to get the free products given for laptop you can do the following query
SELECT freeProdId from Promotion where prodId = 1;
I have given a very simple query to give you a basic understanding. You can modify the query, play around with it and do many things. (Ex. Get the prodName instead of the id)
This is the table of database arrange this type of product table in database
id ----- products ----- free_pro_id
1 ------- laptop --------- 2
2 ------- pen-drive-------- -
3 ------ hard-disk ------- 2
3 ------ hard-disk ------- 4
4 ------- mouse ---------- 3
This is the query to get output of above table
SELECT foo.products ,product.products FROM product foo inner join product on foo.id=product.free_pro_id
I am designing a database to organize materials for 3D production.
Materials are named like 1_Fabric_01_Textile_001_BlueJeans_Denim and 2_Metal_02_BrushedMetal_002_ChromeBrushed_Chrome, etc
So, I need a materials table, which basically has information on material name (last value, look above) and a combination of type and subvariant. Each type has allowed variants like 1_Fabric has 01_Textile, 02_Leather, 2_Metal has 01_Metal, 02_BrushedMetal and so on.
Now making all combinations would not be difficult (i.e., being able to choose every possible subvariant for every material type), but I want to limit the combinations to only allowed combinations, so users cannot choose invalid combinations (like 1_Fabric_01Metal or 2_Metal_01Textile).
Any ideas?
In order to generate those kind of name
1_Fabric_01_Textile
2_Metal_02_BrushedMetal
Based on the followin tables
Type
----------
Id Name
-- ------
1 1_Fabric
2 2_Metal
SubType
------------
Id Name
-- ------
1 01_Textile
2 02_Leather
3 01_Metal
4 02_BrushedMetal
And keeping rules on what types can relate to subtypes
You ill need a relational table like:
Type_SubType
-----------------
TypeId SubTypeId
------ ---------
1 1
1 2
2 3
2 4
and if you need more levels of subtypes you can add more tables
1_Fabric_01_Textile_001_BlueJeans_Denim
2_Metal_02_BrushedMetal_002_ChromeBrushed_Chrome
SubSubType
--------------
Id Name
-- ----------
1 001_BlueJeans_Denim
2 002_ChromeBrushed_Chrome
Type_SubType_SubSubType
-------------------------
TypeId SubTypeId SubSubType
------ --------- ----------
1 1 1
2 3 2
Now the trick part is to do a better normalization for the third level relation. It can be achieved if you add a identity column to the first relational table
So instead you can use this example:
Type_SubType
---------------------
Id TypeId SubTypeId
-- ------ ---------
1 1 1
2 1 2
3 2 3
4 2 4
and relating it to the second relational table
Type_SubType_SubSubType
-------------------------
Type_SubTypeId SubSubType
-------------- ----------
1 1
3 2
to retrieve only the possible matches is trivial
select * from type tp
join Type_SubType tp_sb on tp_sb.TypeId = tp.Id
join SubType sb on sb.Id = yb_sb.SubTypeId
or just (if you already selected a type and put it in the variable #TypeId)
Select * from SubType sb
join Type_SubType tp_sb on tp_sb.SubTypeId = sb.Id
where tp_sb.TypeId = #TypeId
and so on for SubSubTypes
note: this solutions only covers a fixed (or maxed) number of sub-sub. To get a total dynamic level of abstractions you ill need a recursive FK. Not something like rocket science but if you still the basics on SQL try stick with the most simple example.
I am trying to use the ConcatRelated function to provide a summary report of the prior day's absences, tardies, and vacations. I have tried several variations and can't seem to get it to work in an Access Query. My table looks as below:
ID A_date Area ATV_Shift Associate_Name Absent Tardy Vacation Reason
-- --------- ----------- --------- -------------- ------ ----- -------- --------------
1 1/11/2015 Asm Kenmore First Keon Wilson 1 Sick
2 1/11/2015 Asm Kenmore First Frank Burns 1 Doctor
3 1/11/2015 Asm Kenmore Second Paul Mattocks 1 FLMA
4 1/11/2015 Decoration First Jane Doe 1 Car Broke Down
5 1/11/2015 Asm Maytag Second John Doe 1
I need to make a query that displays the previous days data (Date()-1). The reasons need to be separated by spaces. I can get everything else to sum in a query but I am unable to get the reasons to concat. I have tried following the examples but just cant get it to function. I was only able to get it to work using a simple SQL query but that returned lines for each reason not in one cell.
I changed your A_date values to 1/13/2015 and stored those sample data in a table named YourTable. Using that table, this is the output in Access 2010 from the query below.
A_date SumOfAbsent SumOfTardy SumOfVacation Reasons
--------- ----------- ---------- ------------- -------------------------------
1/13/2015 5 Car Broke Down Doctor FLMA Sick
SELECT
y.A_date,
Sum(y.Absent) AS SumOfAbsent,
Sum(y.Tardy) AS SumOfTardy,
Sum(y.Vacation) AS SumOfVacation,
ConcatRelated(
'Reason',
'YourTable',
'A_date=Date()-1',
'Reason',
' '
) AS Reasons
FROM YourTable AS y
WHERE y.A_date = Date()-1
GROUP BY y.A_date;
QUESTION: Is it okay to have "shortcut" identifiers in a table so that I don't have to do a long string of joins to get the information I need?
To understand what I'm talking about, I'm going to have to lay ouf an example here that looks pretty complicated but I've simplified the problem quite a bit here, and it should be easily understood (I hope).
The basic setup: A "company" can be an "affiliate", a "client" or both. Each "company" can have multiple "contacts", some of which can be "users" with log in privileges.
`Company` table
----------------------------------------------
ID Company_Name Address
-- ----------------------- -----------------
1 Acme, Inc. 101 Sierra Vista
2 Spacely Space Sprockets East Mars Colony
3 Cogswell Cogs West Mars Colony
4 Stark Industries Los Angeles, CA
We have four companies in our database.
`Affiliates` table
---------------------
ID Company_ID Price Sales
-- ---------- ----- -----
1 1 50 456
2 4 50 222
3 1 75 14
Each company can have multiple affiliate id's so that they can represent the products at different pricing levels to different markets.
Two of our companies are affiliates (Acme, Inc. and Stark Industries), and Acme has two affiliate ID's
`Clients` table
--------------------------------------
ID Company_ID Referring_affiliate_id
-- ---------- ----------------------
1 2 1
2 3 1
3 4 3
Each company can only be a client once.
Three of our companies are clients (Spacely Space Sprockets, Cogswell Cogs, and Stark Industries, who is also an affiliate)
In all three cases, they were referred to us by Acme, Inc., using one of their two affiliate ID's
`Contacts` table
-----------------------------------------
ID Name Email
-- -------------- ---------------------
1 Wylie Coyote wcoyote#acme.com
2 Cosmo Spacely boss#spacely.com
3 H. G. Cogswell ceo#cogs.com
4 Tony Stark tony#stark.com
5 Homer Simpson simpson#burnscorp.com
Each company has at least one contact, but in this table, there is no indication of which company each contact works for, and there's also an extra contact (#5). We'll get to that in a moment.
Each of these contacts may or may not have a login account on the system.
`Contacts_type` table
--------------------------------------
contact_id company_id contact_type
---------- ---------- --------------
1 1 Administrative
2 2 Administrative
3 3 Administrative
4 4 Administrative
5 1 Technical
4 2 Technical
Associates a contact with one or more companies.
Each contact is associated with a company, and in addition, contact 5 (Homer Simpson) is a technical contact for Acme, Inc, and contact 4 (Tony Stark) is a both an administrative contact for company 4 (Stark Industries) and a technical contact for company 3 (Cogswell Cogs)
`Users` table
-------------------------------------------------------------------------------------
ID contact_id company_id client_id affiliate_id user_id password access_level
-- ---------- ---------- --------- ------------ -------- -------- ------------
1 1 1 1 1 wylie A03BA951 2
2 2 2 2 NULL cosmo BF16DA77 3
3 3 3 3 NULL cogswell 39F56ACD 3
4 4 4 4 2 ironman DFA9301A 2
The users table is essentially a list of contacts that are allowed to login to the system.
Zero or one user per contact; one contact per user.
Contact 1 (Wylie Coyote) works for company 1 (Acme) and is a customer (1) and also an affiliate (1)
Contact 2 (Cosmo Spacely) works for company 2 (Spacely Space Sprockets) and is a customer (2) but not an affiliate
etc...
NOW finally onto the problem, if there is one...
Do I have a circular reference via the client_id and affiliate_id columns in the Users table? Is this a bad thing? I'm having a hard time wrapping my head around this.
When someone logs in, it checks their credentials against the users table and uses users.contact_id, users.client_id, and users.affiliate_id to do a quick look up rather than having to join together a string of tables to find out the same information. But this causes duplication of data.
Without client_id in the users table, I would have to find the following information out like this:
affiliate_id: join `users`.`contact_id` to `contacts_types`.`company_id` to `affiliates`.`company_id`
client_id: join `users`.`contact_id` to `contacts_types`.`company_id` to `clients`.`company_id`
company_id: join `users`.`contact_id` to `contacts_types`.`company_id` to `company`.`company_id`
user's name: join `users`.`contact_id` to `contacts_types`.`contact_id` to `contacts`.`contact_id` > `name`
In each case, I wouldn't necessarily know if the user even has an entry in the affiliate table or the clients table, because they likely have an entry in only one of those tables and not both.
Is it better to do these kinds of joins and thread through multiple tables to get the information I want, or is it better to have a "shortcut" field to get me the information I want?
I have a feeling that over all, this is overly complicated in some way, but I don't see how.
I'm using MySQL.
it's better to do the joins. you should only be denormalizing your data when you have timed evidence of a slow response.
having said that, there are various ways to reduce the amount of typing:
use "as" to give shorter names to your fields
create views. these are "virtual tables" that already have your standard joins built-in, so that you don't have to repeat that stuff every time.
use "with" in sql. this lets you define something like a view within a single query.
it's possible mysql doesn't support all the above - you'll need to check the docs [update: ok, recent mysql seems to support views, but not "with". so you can add views to do the work of affiliate_id, client_id etc and treat them just like tables in your queries, but keeping the underlying data nicely organised.]
I have a table User that stores user information - such as name, date of birth, locations, etc.
I have also created a link table called User_Options - for the purpose of storing multi-value attributes - this basically stores the checkbox selections.
I have a front-end form for the user to fill in and create their user profile. Here are the tables I have created to generate the checkbox options:
Table User_Attributes
=====================
id attribute_name
---------------------
1 Hobbies
2 Music
Table User_Attribute_Options
======================================
id user_attribute_id option_name
--------------------------------------
1 1 Reading
2 1 Sports
3 1 Travelling
4 2 Rock
5 2 Pop
6 2 Dance
So, on the front-end form there are two sets of checkbox options - one set for Hobbies and one set for Music.
And here are the User tables:
Table User
========================
id name age
------------------------
1 John 25
2 Mark 32
Table User_Options
==================================================
id user_id user_attribute_id value
--------------------------------------------------
1 1 1 1
2 1 1 2
3 1 2 4
4 1 2 5
5 2 1 2
6 2 2 4
(in the above table 'user_attribute_id' is the ID of the parent attribute and 'value' is the ID of the attribute option).
So I'm not sure that I've done all this correctly, or efficiently. I know there is a method of storing hierarchical data in the same table but I prefer to keep things separate.
My main concern is with the User_Options table - the idea behind this is that there only needs to be one link table that stores multi-value attributes, rather than have a table for each and every multi-value attribute.
The only thing I can see that I'd change is that in the association table, User_Options, you have an id that doesn't seem to serve a purpose. The primary key for that table would be all three columns, and I don't think you'd be referring to the options a user has by an id--you'd be getting them by user_id/user_attribute_id. For example, give me all the user options where user is 1 and user attribute id is 2. Having those records uniquely keyed with an additional field seems extraneous.
I think otherwise the general shape of the tables and their relationships looks right to me.
There's nothing wrong with how you've done it.
It's possible to make things more extensible at the price of more linked table references (and in the composition of your queries). It's also possible to make things flatter, and less extensible and flexible, but your queries will be faster.
But, as is usually the case, there's more than one way to do it.