views:

49

answers:

3

I am designing the database for a shopping cart and I am having trouble deciding which way to approach this problem.

There are three tiers that can items can be restricted to:

1) Local Delivery Only

2) Shipping Available a) Country b) State c) Region

I am thinking to go with a structure like this:

product_shipping_restrictions - key(int), productId(int), local_only(enum('y', 'n'), countries(enum('y', 'n'), states(enum('y', 'n'), regions(enum('y', 'n')

Then if there is a flag for any of them check the corresponding table e.g.

product_shipto_states - key(int), productId(int), stateId(int)

So for example if product 10 is restricted to only ship to Australia and the states NSW and QLD we would have:

product_shipping_restrictions - NULL, 10, 'n', 'y', 'y', 'n'

and

product_shipto_countries - NULL, 10, AU

product_shipto_states - NULL, 10, 1 & NULL, 10, 2

Can you guys think of a better way to achieve this result?

P.s. Sorry for the formatting!

A: 

You could have special rows in the products_shipto_countries and product_shipto_states tables to show 'any' or 'all' or 'none', and then you wouldn't have to worry about whether or not to check those tables; you'd do so all the time. That would leave fewer paths through the code, at the expense of perhaps unnecessary reads.

An additional question would be how to decide you can ship a product to anywhere except certain countries, states, etc. Would you want to list all the possibilities or have 'not' rows in your tables?

Brian Hooper
Yea, i thought about having not rows, but most products would probably only ship within their country of origin and if we add more countries the not rows would probably exceed the other rows.
Ken Greeff
A: 

Perhaps this is one of those cases where an EAV table could be useful.

Enitity, Attribute, Value where Attribute is the Code of the country

product, country, state

10, AU, NSW 10, AU, QLD 10, US, ALL

Not exactly sure how it could handle regions unless States could be made unique in some fashion.

Cups
Definitely need to include regions and would probably get very messy as there could be 10-20 regions per state. Looking into EAV though...
Ken Greeff
A: 

It may help to use table of allowed destinations, instead of focusing on restrictions. The geography table lists all possible destinations that one may ship to. The allow_shipping table defines allowed destinations for each product. Note that term "local only" is a bit ambiguous -- local to whom?

alt text

create table product (
      ProductId   integer not null
    , ProductName varchar(128)
);
alter table product add CONSTRAINT pk_product PRIMARY KEY (ProductId);


create table geography (
      GeographyId integer not null
    , Country     varchar(50)
    , State       varchar(50)
    , Region      varchar(50)
);
alter table geography add CONSTRAINT pk_geography PRIMARY KEY (GeographyId);


create table allow_shipping (
      ProductId   integer not null
    , GeographyId integer not null 
    , Allowed     enum('y','n')
);
alter table allow_shipping 
    add CONSTRAINT pk_allowshipping  PRIMARY KEY (ProductId, GeographyId)
  , add CONSTRAINT fk1_allowshipping FOREIGN KEY (ProductId)   REFERENCES product   (ProductId)
  , add CONSTRAINT fk2_allowshipping FOREIGN KEY (GeographyId) REFERENCES geography (GeographyId)
;
Damir Sudarevic
Hi Damir, thanks for that, i think we are getting close. Local is local to the product say a 10km radius (will be explained properly on the site)I like your allow shipping table but what do you think of having the geography table like GeographyId(PK), GeographyType(CHAR(1)), ParentId(INT) so that i can link them to the existing tables of Countries, States and Regions?
Ken Greeff
Sure, that would work too, though having it de-normalized (one table) speeds-up lookups. Depends on the rest of the model. Is the geography just a lookup or do you use some other types of geo data? For lookups, one table is good -- if interested in geo-aware apps, the other approach sounds better.
Damir Sudarevic
Yea, the model is already built like that. Thanks a lot for your help Damir, you're a legend.
Ken Greeff