Database Management
 
Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
User Name:
Password:
Remember me
Go Back   Dev Shed ForumsDatabasesDatabase Management

Reply
Add This Thread To:
  Del.icio.us   Digg   Google   Spurl   Blink   Furl   Simpy   Y! MyWeb 
Thread Tools Search this Thread Rate Thread Display Modes
 
Unread Dev Shed Forums Sponsor:
You don't need a fax machine to get faxes. Get a fax-to-email fax number from CallWave. Try it free.
  #1  
Old May 13th, 2003, 10:19 AM
Franz Fortuny Franz Fortuny is offline
Junior Member
Dev Shed Newbie (0 - 499 posts)
 
Join Date: May 2003
Location: Yucatan, Mexico
Posts: 5 Franz Fortuny User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
Send a message via Yahoo to Franz Fortuny
Normalizing / Denormalizing

We have a database of about 600,000 live (active) items.

So far each item has one and only one price at which it is sold.

SOME items (not all of them, a minority) will eventually sell at different prices in SOME stores.

I suggested to add a table:

iditem
idStoreType
price

And insert here ONLY the items that have a different price at the special store.

If the idStoreType/iditme combination is NOT FOUND, then the selling price for this item is the one already stored in our 600,000-item table at the "price" column.

Another person suggests that we should create a table:

iditem
idstoretype
price

And add there all 600,000 items for the time being and use this new table from now on. If prices change for another store or store type, then all 600,000 rows of the new

iditem-idstoretype-price

should be inserted, even though 98.5% of all rows will have exactly the same price for the same combination of IDITEM-ITSTORTYPE.

How should this be managed? Also, consider the fact that items with a different price at special stores will eventually go back to the same "central" price.

Thank you for any advise on this.

My suggestion includes the creation of a view that will yield the selling price, giving always the right one. Could also be a procedure.

Last edited by Franz Fortuny : May 13th, 2003 at 10:32 AM.

Reply With Quote
  #2  
Old May 13th, 2003, 11:51 AM
bcyde's Avatar
bcyde bcyde is offline
Me likey breadsticks...
Dev Shed Beginner (1000 - 1499 posts)
 
Join Date: Jan 2003
Location: Los Angeles
Posts: 1,189 bcyde User rank is Sergeant (500 - 2000 Reputation Level)bcyde User rank is Sergeant (500 - 2000 Reputation Level)bcyde User rank is Sergeant (500 - 2000 Reputation Level)bcyde User rank is Sergeant (500 - 2000 Reputation Level)bcyde User rank is Sergeant (500 - 2000 Reputation Level) 
Time spent in forums: 3 Days 1 h 12 m 57 sec
Reputation Power: 12
Send a message via AIM to bcyde Send a message via Yahoo to bcyde
Sounds like some type of discount system.

If so, will the discounts be applied across the board to all items in a store or on specific items?
My quick idea if you absolutely know that it's on a per store basis you might be able to create a new table by storetype and a discount percentage. If not you can create a discount item table with storetype, itemid and discount percentage.

Then when you get the price just multiply the discount percentage with the actual price, and use COALESCE with 1 as the default for when there's no discounted price.

Not sure if it will work in your case, but that's what popped into my head as a probable quick solution.

-b
__________________
PostgreSQL, it's what's for dinner...

Reply With Quote
  #3  
Old May 14th, 2003, 05:27 PM
rycamor rycamor is offline
Gödelian monster
Dev Shed Regular (2000 - 2499 posts)
 
Join Date: Jul 1999
Location: Pembroke Pines, Florida, USA
Posts: 2,298 rycamor User rank is Sergeant Major (2000 - 5000 Reputation Level)rycamor User rank is Sergeant Major (2000 - 5000 Reputation Level)rycamor User rank is Sergeant Major (2000 - 5000 Reputation Level)rycamor User rank is Sergeant Major (2000 - 5000 Reputation Level)rycamor User rank is Sergeant Major (2000 - 5000 Reputation Level)rycamor User rank is Sergeant Major (2000 - 5000 Reputation Level) 
Time spent in forums: 3 Days 1 h 54 m 21 sec
Reputation Power: 41
I see no problem with the original concept of a small table that only has information for products with altered prices.

It's not a question of normalization, but of logical design. Normalization only answers a small part of the overall questions needed to design a database for serious operations.

This is actually a classic approach to the "missing information" problem: Most of your stores don't have a special price, so why create a record to say that fact? And, this solution can grow in both directions. If it seems like many stores will have special prices, grow the table. Or, if you are phasing out these special prices, shrink the table.

The only thing to be careful with is your logic in processing orders, adding products, or updating products. You will definitely want to use view with well-tested queries, and maybe a trigger or two. You need to make sure that the "special" prices can't be circumvented accidentally by your application.

Performance might be a problem in all this, though, especially if there are many special prices. Hmmm... maybe I am missing somthing...

Quote:
SOME items (not all of them, a minority) will eventually sell at different prices in SOME stores.

Are these changed prices different for each store, or will all stores with a different price for a certain product have the same different price?

Quote:
iditem
idStoreType
price


idStoreType would lead me to think that you are applying different prices for a certain product to a group of stores. Or should that be idStore?

Depending on the answer to the above two questions, there might be better-performing ways to deal with the problem.

Expressing your design in terms of a predicate would be useful here.
__________________
The real n-tier system:

FreeBSD -> PostgreSQL -> [any_language] -> Apache -> Mozilla/XUL

Amazon wishlist -- rycamor (at) gmail.com

Reply With Quote
  #4  
Old May 14th, 2003, 06:26 PM
Franz Fortuny Franz Fortuny is offline
Junior Member
Dev Shed Newbie (0 - 499 posts)
 
Join Date: May 2003
Location: Yucatan, Mexico
Posts: 5 Franz Fortuny User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
Send a message via Yahoo to Franz Fortuny
Your perception is correct

Your perception is correct. The table would be:

iditem
idStoreType (group)
SellingPrice

iditem,idStoreType are unique (primary key) on this table.

The order of events would be:

1) The item is normally entered in the database with a regular selling price.

2) If the item should be offered at higher or lower prices at one or more groups of stores, then a row would be created for each exception.

3) The application will simply require the selling price of a specific item at a specific idStoreType. If the result is NULL, then it will simply request the price from the original, huge table that contains all prices.

This can be solved with a view which consists of a union of two record sets: one in which the idStoreType is always null and the other in which it is NEVER null.

select price from vwprices where
(idGroup=? and idItem=?)
or
(idGroup is null and idItme=?)
order by idGroup desc


The record set will consist of at the most 2 rows. We are interested in the first one, thus the "order by" clause.

There shouldn't be a performance problem, since the view will cause the plan to use the indexes (unique in both cases).

Most of the time the first part of the query will bring nothing, and ONE and only ONE item from the second part will always be present, since all items do exist on the main, huge table.

What do you think?

The union would be something like this:

create view vwprices(idItem,idGroup,price) as
select idItem, cast(null as smallint) as idGroup, price from main table
union
select idItem, idGroup, price from smalltable


What do you think?

Last edited by Franz Fortuny : May 14th, 2003 at 06:30 PM.

Reply With Quote
  #5  
Old May 15th, 2003, 10:09 AM
rycamor rycamor is offline
Gödelian monster
Dev Shed Regular (2000 - 2499 posts)
 
Join Date: Jul 1999
Location: Pembroke Pines, Florida, USA
Posts: 2,298 rycamor User rank is Sergeant Major (2000 - 5000 Reputation Level)rycamor User rank is Sergeant Major (2000 - 5000 Reputation Level)rycamor User rank is Sergeant Major (2000 - 5000 Reputation Level)rycamor User rank is Sergeant Major (2000 - 5000 Reputation Level)rycamor User rank is Sergeant Major (2000 - 5000 Reputation Level)rycamor User rank is Sergeant Major (2000 - 5000 Reputation Level) 
Time spent in forums: 3 Days 1 h 54 m 21 sec
Reputation Power: 41
Looks good to me. To comment in any further detail I would need to know more about your logical model, business rules, etc... but I think you are on the right track.

Reply With Quote
  #6  
Old May 15th, 2003, 11:40 PM
merl merl is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Aug 2002
Posts: 51 merl User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 5 h 6 m 34 sec
Reputation Power: 6
I don't think that a view is a very efficient way to go here because from what I understand of your situation, there is a cartesian join between store and item.

Does your database support functions? If so, I would do it that way.

E.g.

PHP Code:
 select f_get_price(iditemidgroupfrom dual;

CREATE OR REPLACE FUNCTION F_GET_PRICE(
    
iditem_ INTEGER,
    
idgroup_ INTEGER
) RETURN INTEGER AS
    
price_ INTEGER;
BEGIN
    SELECT MAX
(PRICE) -- Will return null if no matching row
    INTO price_
    FROM GROUP_PRICE GP
GROUP G
    WHERE G
.IDGROUP idgroup_
        
AND GP.IDGROUPTYPE G.IDGROUPTYPE
        
AND GP.IDITEM iditem_;
    
    if (
price_ is nullthen
        SELECT PRICE
        INTO price_
        FROM ITEM
        WHERE IDITEM 
iditem_;
    
end if;
    RETURN 
price_;
END;
/
SHOW ERRORS


This example is in pl/sql (oracle), but you could do this in any db that supports functions.

If your db doesn't support functions (boo) then it's probably most efficient to code this in your application layer. That makes it two separate db calls, but doesn't load your db down as much.

Reply With Quote
  #7  
Old May 16th, 2003, 09:26 AM
Franz Fortuny Franz Fortuny is offline
Junior Member
Dev Shed Newbie (0 - 499 posts)
 
Join Date: May 2003
Location: Yucatan, Mexico
Posts: 5 Franz Fortuny User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
Send a message via Yahoo to Franz Fortuny
This:

Quote:
SELECT MAX(PRICE) -- Will return null if no matching row
INTO price_
FROM GROUP_PRICE GP, GROUP G
WHERE G.IDGROUP = idgroup_
AND GP.IDGROUPTYPE = G.IDGROUPTYPE
AND GP.IDITEM = iditem_;


can become this:

select price into price from special_prices
where iditem=:iditem and idgroup = :idgroup


iditem + idgroup ARE the primary key of the special_prices table.

No need for any of the other comparisons.

The program already knows the IDGROUP and the IDITEM (idgroup is a variable that takes a value as the application starts, and iditem is obtained when the item's barcode is read).

That's why the view is efficient. The plan used shows that it will only use indexes.

Did I miss something?

Reply With Quote
  #8  
Old May 16th, 2003, 09:59 AM
Franz Fortuny Franz Fortuny is offline
Junior Member
Dev Shed Newbie (0 - 499 posts)
 
Join Date: May 2003
Location: Yucatan, Mexico
Posts: 5 Franz Fortuny User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
Send a message via Yahoo to Franz Fortuny
I ran the following:

create table specprice
(
numart integer not null,
group smallint not null,
primary key (group,numart),
price double precision
)##

insert into specprec select numart,4,regprice*.95 from pvartics where numart>900000 and rownum < 1000##

create view vpre(numart,group,price) as
select numart,cast(null as smallint) as group,price from pvartics
union
select numart,group,precio from specprice##

explain plan for
select * from vpre where (numart=600500 and group=6)
or
(numart=600500 and group is null) ##

--

The plan always uses primary key indexes. Response is instantaneous.

Table PVARTICS contains 1.2 million rows. Table SPECPRICE contains about 6,000 rows.

The view does work. This is from a real database where the small table was added and the insertions were made for experimentation.

Reply With Quote
Reply

Viewing: Dev Shed ForumsDatabasesDatabase Management > Normalizing / Denormalizing


Thread Tools  Search this Thread 
Search this Thread:

Advanced Search
Display Modes  Rate This Thread 
Rate This Thread:


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
View Your Warnings | New Posts | Latest News | Latest Threads | Shoutbox
Forum Jump

 Free IT White Papers!
 
Accelerating Trading Partner Performance
One in five. That's how many partner transactions have at least one error. That is an amazing statistic, particularly given the extraordinary leaps in innovation across the global supply chain during the past two decades. Download this white paper to learn more.

 
Competing on Analytics
This Tech Analysis is designed to help identify characteristics shared by analytics competitors, and includes information about 32 organizations that have made a commitment to quantitative, fact-based analysis.

 
Cost Effective Scaling with Virtualization and Coyote Point Systems
An overview of the industry trend toward virtualization, how server consolidation has increased the importance of application uptime and the steps being taken to integrate load balancing technology with virtualized servers.

 
Five Checkpoints to Implementing IP Telephony
Implementation planning for IP PBX software and IP telephony has become vital as businesses replace discontinued legacy PBX phone systems. This informative whitepaper outlines five "checkpoints" for any implementation plan that will help make IP communications a successful proposition.

 
Hosted Email Security: Staying Ahead of New Threats
In the last two years, email has become a fierce battleground between the nefarious forces of spam and malware, and the heroes of messaging protection. The spam volumes increased alarmingly every month, bringing clever new forms of phishing and virus propagation attacks.

 

Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
  
 





© 2003-2008 by Developer Shed. All rights reserved. DS Cluster 4 hosted by Hostway