April 12, 2003 at 3:02 pm
Hi folks,
I have been trying to implement a database solution that will sell lots of different, disparate, products.The problem is that some of the products can be sold with additional components installed.(I have already suggested that maybe we should sell the components as a separate entity, but they weren’t too keen on this 🙁
I am unsure how to solve this issue.I believe that it would not be good practice to set up a different table for each product?
I have set up a table to deal with the generic attributes of all products.
tblBaseProducts
baseProductId
categoryId
capacity
length
width
height
weight
Now, as we may be selling the same product to different clients
At different prices, I set up the following table, which will allow me to do this.
tblProductSales
baseProductId
productId
unitPrice
leadTime
Now, in order to deal with the additional components, would it be a good idea to set up a new table for each additional component that a product has eg, a “shopping cart” that has a “babychair” component
tblProductBabychair
baseProductId
productId
isBabyChair (bit value)
As you can see, I am a bit confused.But I feel that I understand database concepts pretty well.If anyone can help, I’d really appreciate it.
Many thanks,
Yogi.
April 13, 2003 at 2:12 pm
I would recommend maybe a product component table. This would be a 1 to many relationship that can tie additional components to a given product. This table could have baseProductId and a ComponentProductId. If your saying that the components need the same characteristics as the products then the componentID is a product ID. I would NOT use something like isBabyChair. Way too limiting. Use something like ComponentTypeCd and componentValue. THen you could have a ComponentType table with something like Type = "BC", Decode = "BabyChair". Let me know if this makes sense.
Darren
Darren
April 14, 2003 at 7:44 am
Hi Darren,
Thanks for the reply.
I have created a table tblProductComponent
It has the following fields
tblProductComponent
baseProductId (references tblProduct.baseProducId)
componentProductId (references tblComponent)
So I can now run the follwing storeProc that will return all the trolleys that have a “babychair” component
CREATE PROCEDURE spGetAllBabyChairTrolleys
(
@componentCategoryId INT
)
AS
SELECT p. baseProductId, p.shortDescription
FROM tblProducts p, tblComponent c, tblProductComponent pc
WHERE c.categoryId = @componentCategoryId
AND pc.componentId = c.componentId
AND p. baseProductId = pc. baseProductId
GO
Do you think that this is the best solution to use?Would this be what you would do?
Also, this storedProc is hard-coded to only bring back a product that contains a single component.
Would there be any way to have a storedProc that potentially received MULTIPLE input parameters, and returned all the trolleys that satisfied this criteria?
e.g , when User selects multiple component CategoryId’s from a dropdown list?Sorry to ask, you’ve already helped more than you know.
I feel as if i am almost there.Can anyone suggest anything?
Cheers,
yogi
April 14, 2003 at 7:44 am
Hi Darren,
Thanks for the reply.
I have created a table tblProductComponent
It has the following fields
tblProductComponent
baseProductId (references tblProduct.baseProducId)
componentProductId (references tblComponent)
So I can now run the follwing storeProc that will return all the trolleys that have a “babychair” component
CREATE PROCEDURE spGetAllBabyChairTrolleys
(
@componentCategoryId INT
)
AS
SELECT p. baseProductId, p.shortDescription
FROM tblProducts p, tblComponent c, tblProductComponent pc
WHERE c.categoryId = @componentCategoryId
AND pc.componentId = c.componentId
AND p. baseProductId = pc. baseProductId
GO
Do you think that this is the best solution to use?Would this be what you would do?
Also, this storedProc is hard-coded to only bring back a product that contains a single component.
Would there be any way to have a storedProc that potentially received MULTIPLE input parameters, and returned all the trolleys that satisfied this criteria?
e.g , when User selects multiple component CategoryId’s from a dropdown list?Sorry to ask, you’ve already helped more than you know.
I feel as if i am almost there.Can anyone suggest anything?
Cheers,
yogi
April 14, 2003 at 11:21 am
Sorry folks, I accidentally posted the reply twice. yogi
April 14, 2003 at 2:10 pm
yogiberr, This is not unlike a Part's relationship to its Bill of Materials. Each Part can be made up of many other Parts. In theory, you'll only need a tblPart, tblBOM, and tblBOMPart.
tblPart:
PartID,
PartNumber,
.
.
.
BOMID
tblBOM
BOMID,
.
.
.
tblBOMPart
BOMID
PartID
.
.
.
You can now enforce integrity of the Bill of Materials by making sure nothing gets into tblBOMPart that isn't already in Part and making sure that no Part in tblPart gets killed if it resides in a BOM (tblBOMPart). This model also suggests the capability for 'exploded' BOMS in which a single end-product is made up of multiple sub-assemblies and/or parts, and each sub-assembly is made up of multiple sub-assemblies and/or parts, etc..., etc... (it's turtles all the way down ).
This is largely the same as your proposal, with the exception that we've removed the necessity of a separate Component table.
HTH,
SJTerrill
April 14, 2003 at 3:20 pm
Hi SJ,
Thanks for the reply.I have studied the example but am still a bit confused.I have included my questions next to your post.I hope you don't mind. 🙂
In fact maybe if I left an example.
Eg, if I have a part, with a partId of 1, which is made up of two parts: partId = 2, and partId =3
Please do not think that I am being lazy, I feel that I almost grasp it, but maybe if you could fill in the example..I'd be really grateful.
tblPart:
PartID,
PartNumber, ( do I need this field?)
.
.
.
BOMID (
tblBOM
BOMID, (do I insert a random number here?)
. (what other fields would I need?)
.
.
tblBOMPart
BOMID
PartID (does this reference tblPart.PartID)
.
.
Many thanks,
yogiberr
April 14, 2003 at 4:58 pm
yogiberr, no fear! You've not been interpreted as lazy! Following are some brief responses. If this remains clear as mud, I'll try and dig up a real-world example from my bag of tricks.
tblPart:
PartID,
PartNumber, ( do I need this field?) --SJT--Strictly speaking, No. However, I'm of the school that use of a simple datatype for a primary key (e.g., int) is preferable to other methods. The PartID is assumed to be an int PK. The PartNumber is how the part is represented to humans.
.
.
.
BOMID (
tblBOM
BOMID, (do I insert a random number here?) --SJT--No. This follows the same principle as the PartID, above. You could use an identity column, but I'd be interested it what others think about using identities for PKs... anyone?
. (what other fields would I need?) --SJT-- How about: BOMName, BOMRevision, EffectivityDate, ExpiryDate. It REALLY depends on your needs. Since this sounds like a sales order management system, the BOM data may not need to be highly robust.
.
.
tblBOMPart
BOMID
PartID (does this reference tblPart.PartID) --SJT--You get it exactly!
.
.
Regards,
SJTerrill
April 15, 2003 at 9:49 am
Hi SJ,
Thanks for the reply.I think I am following.
Eg, if I had a part, partId 1, which was made up of 2 other parts,
Eg, partId 2 and partId 3
Would the tables be as follows?
tblPart:
PartID 1, 2, 3
.
.
BOMID 1
tblBOM
BOMID 1
.
.
tblBOMPart
BOMID 1, 1
PartID 2, 3
Is this correct? In tblBOMBPart, are both fields primary keys? Is it true that the PartID of the of the non-constituent Part should NOT appear in tblBOMPart?
Even if by some miracle I have managed to get this right, is there any chance you could include a small example?I am under serious pressure at this stage. I understand that you might not have time to include an example.But if you could tell me that I have followed you correctly, that’d be great.
Many thanks.
yogiberr
April 15, 2003 at 12:11 pm
yogiberr, You have indeed followed correctly. You may want to use table & column names more familiar to users of an order management system: Part or Product for Part, Kit (maybe) for BOM, and KitPart for BOMItem.
It is the combination of the BOM (Kit) ID and Part ID columns that comprise the primary key in the BOMItem (KitPart) table. You understand exactly!
I'll post a sample after I get off work today. That'll be evening EDT sometime.
HTH,
SJTerrill
April 15, 2003 at 4:27 pm
Hi SJ, that's a great relief to know that I am getting there.Thanks for the help.If you do manage to get time to post a small example, I'd really appreciate it.
All the best from sunny scotland,
yogiberr
April 15, 2003 at 4:57 pm
yogiberr, I just scripted out this structure (SQL2K). Only three tables and barebones columns, but I hope it helps. Just create an empty database and run this.
The structure explicitly requires a Part record before any other record may be populated in any other table. Obviously, you'll have to insert a BOM record before a BOMPart, as well.
Regards from the US,
SJTerrill
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[FK_tblBOMPart_tblBOM]') and OBJECTPROPERTY(id, N'IsForeignKey') = 1)
ALTER TABLE [dbo].[tblBOMPart] DROP CONSTRAINT FK_tblBOMPart_tblBOM
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[FK_tblPart_tblBOM]') and OBJECTPROPERTY(id, N'IsForeignKey') = 1)
ALTER TABLE [dbo].[tblPart] DROP CONSTRAINT FK_tblPart_tblBOM
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[FK_tblBOMPart_tblPart]') and OBJECTPROPERTY(id, N'IsForeignKey') = 1)
ALTER TABLE [dbo].[tblBOMPart] DROP CONSTRAINT FK_tblBOMPart_tblPart
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[tblBOM]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[tblBOM]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[tblBOMPart]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[tblBOMPart]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[tblPart]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[tblPart]
GO
CREATE TABLE [dbo].[tblBOM] (
[BOMID] [int] NOT NULL ,
[BOMName] [varchar] (64) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[tblBOMPart] (
[BOMID] [int] NOT NULL ,
[PartID] [int] NOT NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[tblPart] (
[PartID] [int] NOT NULL ,
[PartNumber] [varchar] (64) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
[BOMID] [int] NULL
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[tblBOM] WITH NOCHECK ADD
CONSTRAINT [PK_tblBOM] PRIMARY KEY CLUSTERED
(
[BOMID]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[tblBOMPart] WITH NOCHECK ADD
CONSTRAINT [PK_tboBOMPart] PRIMARY KEY CLUSTERED
(
[BOMID],
[PartID]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[tblPart] WITH NOCHECK ADD
CONSTRAINT [PK_tblPart] PRIMARY KEY CLUSTERED
(
[PartID]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[tblBOMPart] ADD
CONSTRAINT [FK_tblBOMPart_tblBOM] FOREIGN KEY
(
[BOMID]
) REFERENCES [dbo].[tblBOM] (
[BOMID]
),
CONSTRAINT [FK_tblBOMPart_tblPart] FOREIGN KEY
(
[PartID]
) REFERENCES [dbo].[tblPart] (
[PartID]
)
GO
ALTER TABLE [dbo].[tblPart] ADD
CONSTRAINT [FK_tblPart_tblBOM] FOREIGN KEY
(
[BOMID]
) REFERENCES [dbo].[tblBOM] (
[BOMID]
)
GO
Edited by - TheWildHun on 04/15/2003 4:57:26 PM
April 16, 2003 at 9:43 am
Hi SJ,
magic.It's the breakthru I was needing.I'm now in the process of running queries which return all the products that compose the main product.
Many, many thanks to yourself and also to Darren.
Ta,
yogiberr
Viewing 13 posts - 1 through 12 (of 12 total)
You must be logged in to reply to this topic. Login to reply