Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2000 Forums
 SQL Server Development (2000)
 Price Lists, what to do?

Author  Topic 

MikeB
Constraint Violating Yak Guru

387 Posts

Posted - 2004-04-19 : 12:47:45
I am trying to develop an estimation software package and I am a little confused about the table structure required to provide price list(s) for the takeoff portion of the software. There are many different item types to be included in the takeoff and each has a unique process that determines the prices.

Example, the main product is concrete components, so the price of a component is influenced by the price of its aggregates.

Another product is field hardware and cast in hardware which are steel assemblies either used on the construction site or cast into the concrete components. The price of hardware is influenced by the price of its components (Steel flat bar, studded anchors, rebar, etc...)

Also, the estimate will include items for shipping the product, erection of the product, finishing etc....

What I am wondering is....should there be a price list (table) for each item category, or should there be single table for all items.

Some items require information that other items do not, for example, shipping rate would require a company and location, a product rate would not.

I get so confused with this because there is so much. I create a table structure that I think will work but once I get into it, I learn that it does not....

Any thoughts? How would you build this table structure?

Mike B

DustinMichaels
Constraint Violating Yak Guru

464 Posts

Posted - 2004-04-19 : 13:51:57
I'm not an expert in database design but you may want to use the concept of entity sub types.

To do this make a common table which will share all of the attributes for the different products.

tbProduct
intProductID PK
tbName
...

Then you can use 1 to 1 relationships with the tbProduct table to create your entity sub types.

For example for the concrete component products you could have a table like this.

tbConcreteComponent
intProductID PK FK To the tbProduct table.
...

tbConcreteComponentPart
intConcreteComponentPart PK
intProductID FK to tbConcreteCompoent table.
mnyPrice
...


Then for each other type of entity just extend the idea that I used in the tbConcreteComponent table. However, I'm still a newb at database design so you'll still want to get the opinions of the experts on this site.

Good luck.

Dustin Michaels
Go to Top of Page

MikeB
Constraint Violating Yak Guru

387 Posts

Posted - 2004-04-19 : 14:06:34
quote:
Originally posted by DustinMichaels

I'm not an expert in database design but you may want to use the concept of entity sub types.

To do this make a common table which will share all of the attributes for the different products.

tbProduct
intProductID PK
tbName
...

Then you can use 1 to 1 relationships with the tbProduct table to create your entity sub types.

For example for the concrete component products you could have a table like this.

tbConcreteComponent
intProductID PK FK To the tbProduct table.
...

tbConcreteComponentPart
intConcreteComponentPart PK
intProductID FK to tbConcreteCompoent table.
mnyPrice
...


Then for each other type of entity just extend the idea that I used in the tbConcreteComponent table. However, I'm still a newb at database design so you'll still want to get the opinions of the experts on this site.

Good luck.

Dustin Michaels



Good idea, but, if I was to do this, how do I know what table to link to ... or is that a concern since the ProductID is the primary key on the ConcreteComponent table?

Would I LEFT JOIN to all tables on the ProductID when I query the tables?

Mike B
Go to Top of Page

DustinMichaels
Constraint Violating Yak Guru

464 Posts

Posted - 2004-04-19 : 14:23:29
I think LEFT OUTER JOIN could work in this situation, but your select queries would be very complicated (probably have to use alot of case statements).

Perhaps you could create a view that would be the union of all your entity sub types. In this example I'll just assume that you have another entity sub type called tbShippedProduct which should include the shipping cost with the price.

for example

CREATE VIEW viewAllProducts
AS

--UNION together all of the entity sub types.
SELECT tbProduct.intProductID, tbProduct.charName,
SUM(tbConcreteComponentPart.mnyPrice) AS Price,
'Concrete Component' AS ProductType
FROM tbProduct INNER JOIN tbConcrete tbConcreteComponent ON(tbProduct.intProductID = tbConcreteComponent.intProductID) INNER JOIN
tbConcreteComponentPart ON (tbConcreteComponent.intProductID = tbConcreteComponentPart.intProductID)
GROUP BY tbProduct.intProductID

UNION ALL

SELECT tbProduct.intProductID, tbProduct.charName,
tbShippedProduct.mnyShippingPrice
+ tbShippedProduct.mnyPrice AS Price,
'Shipped Product' AS ProductType
FROM tbProduct INNER JOIN tbShippedProduct ON (tbProduct.intProductID = tbShippedProduct.intProductID)

UNION ALL ...continue with other types.

Then for example, you want to do a query on the concrete products you could do the following.

SELECT viewAllProducts.intProductID, viewAllProducts.charName,
viewAllProducts.Price
FROM viewAllProducts
WHERE viewAllProducts.ProductType = 'Concrete Component'


This method may be slow though. There are probably some other alternatives that are much more efficient to this solution.

Good luck.

Dustin Michaels
Go to Top of Page

MikeB
Constraint Violating Yak Guru

387 Posts

Posted - 2004-04-19 : 14:53:09
quote:
Originally posted by DustinMichaels

I think LEFT OUTER JOIN could work in this situation, but your
UNION ALL

.......
......

Dustin Michaels



I just did the DDL with this table structure, and honestly, I am not sure it is the right approach. Check out the DDL and see what you think?


USE NORTHWIND
GO

CREATE TABLE tbProduct (
ProductID INT IDENTITY (1,1) NOT NULL,
Product VARCHAR (100) NOT NULL
)

GO

ALTER TABLE tbProduct
ADD CONSTRAINT tbProduct_pk PRIMARY KEY (ProductID)

GO

CREATE TABLE tbProduct1 (
fkProductID INT NOT NULL,
Var1 FLOAT NOT NULL,
Var2 FLOAT NOT NULL,
)

GO

ALTER TABLE tbProduct1
ADD CONSTRAINT tbProduct1_pk PRIMARY KEY (fkProductID)
GO

ALTER TABLE tbProduct1
ADD CONSTRAINT tbProduct1_fk FOREIGN KEY (fkProductID)
REFERENCES tbProduct (ProductID)
GO

CREATE TABLE tbProduct2 (
fkProductID INT NOT NULL,
Var1 FLOAT NOT NULL,
Var2 FLOAT NOT NULL,
Var3 FLOAT NOT NULL,
)

ALTER TABLE tbProduct2
ADD CONSTRAINT tbProduct2_pk PRIMARY KEY (fkProductID)
GO

ALTER TABLE tbProduct2
ADD CONSTRAINT tbProduct2_fk FOREIGN KEY (fkProductID)
REFERENCES tbProduct (ProductID)
GO

INSERT INTO tbProduct (Product)
SELECT 'First Product'
GO

declare @iProductID int
SELECT @iProductID = @@Identity
INSERT INTO tbProduct1 (fkProductID, Var1, Var2)
SELECT @iProductID, 10, 10
GO

INSERT INTO tbProduct (Product)
SELECT 'Second product'
GO

declare @iProductID int
SELECT @iProductID = @@Identity
INSERT INTO tbProduct2 (fkProductID, Var1, Var2, Var3)
SELECT @iProductID, 10, 10, 10
GO

SELECT p.ProductID, p.Product, One.*, Two.*
FROM tbProduct AS p LEFT JOIN tbProduct1 AS One
ON p.ProductID = One.fkProductID
LEFT JOIN tbProduct2 AS Two
ON p.ProductID = Two.fkProductID
WHERE p.ProductID = 1

GO

DROP TABLE tbProduct1
GO

DROP TABLE tbProduct2
GO

DROP TABLE tbProduct
GO


There just doesn't seem to be any good way to direct the data flow for inserts, deletes, etc....

Also, look what happens when I do a left join. You will get the fields for all products but they will be NULL (as they should be but..)

Mike B

Go to Top of Page

DustinMichaels
Constraint Violating Yak Guru

464 Posts

Posted - 2004-04-19 : 15:48:44
If you don't want to go with the entity sub type method you could just make one table and use alot of case statements in your select commands. Also you'll probably have to use corralated sub queries.

tbProduct
intProductID PK
charName
intProductTypeID FK

tbProductType
intProductTypeID PK
charName

tbConcreteComponentPart
intConcreteComponentPartID PK
intProductID FK to tbProduct.
mnyPrice

tbShippingProduct
intProductID PK and FK to tbProduct
mnyPrice
mnyPriceToShip


Then your select statement could look like this.

SELECT tbProduct.intProductID, tbProduct.charName,
CASE WHEN tbProductType.charName = 'Concrete Component' THEN
(SELECT SUM(tbConcreteComponentPart.mnyPrice)
FROM tbConcreteComponentPart WHERE
tbConcreteComponentPart.intProductID = tbProduct.intProductID)
WHEN tbProductType.charName = 'Shipping' THEN
(SELECT tbShippingProduct.mnyPrice + tbShippingProduct.mnyPriceToShip
FROM tbShippingProduct WHERE tbShippingProduct.intProductID = tbProduct.intProductID)

WHEN ...other types of products

END AS Price

FROM tbProduct


Either way you choose I think it is going to be very complicated to implement.

Dustin Michaels
Go to Top of Page

MichaelP
Jedi Yak

2489 Posts

Posted - 2004-04-19 : 16:22:39
Here's another approach to this problem. Come up with a rules engine to handle this.

Example:
You add "Strong Concrete" and "Rebar" to a project.
Each one of those entity's has a set of rules that calulates its' costs. A "rule" would be a stored proc that takes some standard set of params (probably just the entity ID and maybe a customerID for discounts etc) and the rule would run all the complicated logic to handle shipping, cost of all the materials that make up the entity etc. The Rule's final output will be total cost for that one entity.
You add these two Entity's into some sort of rules processing queue, and you have your rules engine look at each row and "run the rules" to come up with a cost for each of those items. I think you'll still have lots of very different tables to setup and populate for all the different types of components.

Did that make sense?

Michael

<Yoda>Use the Search page you must. Find the answer you will.</Yoda>
Go to Top of Page

MikeB
Constraint Violating Yak Guru

387 Posts

Posted - 2004-04-20 : 08:48:25
quote:
Originally posted by DustinMichaels
...................
.......
tbProduct
intProductID PK
tbName
...




Is tbName supposed to be the name of the product table to look for when manipulating data?

I actually thought of doing this for some other things but alot of people seemed to froun upon the idea!

What does everyone think of doing this?

Mike B
Go to Top of Page

DustinMichaels
Constraint Violating Yak Guru

464 Posts

Posted - 2004-04-20 : 09:15:06
quote:
Originally posted by MikeB

quote:
Originally posted by DustinMichaels
...................
.......
tbProduct
intProductID PK
tbName
...




Is tbName supposed to be the name of the product table to look for when manipulating data?

I actually thought of doing this for some other things but alot of people seemed to froun upon the idea!

What does everyone think of doing this?

Mike B




I just messed up when I wrote down tbName. I meant to say charName. The name should be a column in the tbProduct table not another separate table. But I guess it could be possible to have dynamic table's in which the column tbName could point to. I've never done this before though.

Dustin Michaels
Go to Top of Page

MikeB
Constraint Violating Yak Guru

387 Posts

Posted - 2004-04-21 : 16:51:53
quote:
Originally posted by DustinMichaels

quote:
Originally posted by MikeB

quote:
Originally posted by DustinMichaels
...................
.......
tbProduct
intProductID PK
tbName
...




Is tbName supposed to be the name of the product table to look for when manipulating data?

I actually thought of doing this for some other things but alot of people seemed to froun upon the idea!

What does everyone think of doing this?

Mike B




I just messed up when I wrote down tbName. I meant to say charName. The name should be a column in the tbProduct table not another separate table. But I guess it could be possible to have dynamic table's in which the column tbName could point to. I've never done this before though.

Dustin Michaels


Dustin, I have looked into this sub-type / super type rationalle and I am still a little hesitant but a little more confortable then with the alternatives. Thanks for the suggestions.

Mike B
Go to Top of Page
   

- Advertisement -