views:

141

answers:

2

Hopefully my description is a little better than the title, but basically I'm having an issue with one part of a new application schema and i'm stuck on what is the most manageable and elegant solution in table structure.

Bare bones table structure with only relevant fields showing would be as follows:

airline (id, name, ...)
hotel (id, name, ...)
supplier (id, name, ...)
event (id, name,...)
eventComponent (id,name) {e.g Food Catering, Room Hire, Audio/Visual...}
eventFlight (id, eventid, airlineid, ...)
eventHotel (id, eventid, hotelid, ...)
eventSupplier (id, eventid, supplierid, hotelid, eventcomponentid, ...)

So airline, hotel, supplier are all reference tables, and an Event is create with 1 to many relationships between these reference tables. E.g an Event may have 2 flight entries, 3 Other components entries, and 2 hotel entries. But the issue is that in the EventSupplier table the supplier can be either a Supplier or an existing Hotel. So after the user has built their new event on the front-end i need to store this in a fashion that doesn't make it a nightmare to then return this data later.

I've been doing a lot of reading on Polymorphic relations and exclusive arcs and I think my scenario is definitely more along the lines or an Exclusive Arc relationship.

I was thinking:

CREATE TABLE eventSupplier (
id SERIAL PRIMARY KEY,
eventid INT NOT NULL,
hotelid INT,
supplierid INT,
CONSTRAINT UNIQUE (eventid, hotelid, supplierid), -- UNIQUE permits NULLs
CONSTRAINT CHECK (hotelid IS NOT NULL OR supplierid IS NOT NULL),
FOREIGN KEY (hotelid) REFERENCES hotel(id),
FOREIGN KEY (supplierid) REFERENCES supplier(id)
);

And then for the retrieval of this data just use an outer join to both tables to work out which one is linked.

select e.id as eventid, coalesce(h.name,s.name) as supplier
from eventSupplier es
left outer join
supplier s on s.id = es.supplierid
left outer join
hotel h on h.id = es.hotelid
where h.id is not null OR s.id is not null

My other options were to have a single foreign key in the eventSupplier table with another field for the "type" which seems to be a harder solution to retrieve data from, though it does seem quite flexible if I want to extend this down the track without making schema changes. Or alternately to store the hotelid in the Supplier table direct and just declare some suppliers as being a "hotel" though there were then be redundant data which I don't want.

Any thoughts on this would be much appreciated!

Cheers Phil

A: 

How about handling events one-by-one and using an EventGroup to group them together? alt text

EDIT:

I have simply renamed entities to fit the latest comments. This as close as I can get to this -- admittedly I do not understand the problem properly.

alt text

Damir Sudarevic
Thanks for the ERD Damir I really appreciate you taking the time out to help me. I think i probably needed to clarify the event structure a little further as the grouping approach doesn't really serve any purpose given that each event is in itself treated on a one to one basis.For example I might add a Conference which has a whole heap of data stored in the event table such as approvers, owner, organiser, dates, destination etc, and then it has the additional event components which could be 0..n for each component type.
Phil
So this conference could have 2 flights, 1 hotel booking, and Audio Visual hire and Food Catering which come under Supplier / Other. So the part i am having trouble conceptualising is how I can store a supplier as either a supplier or a hotel taking into account both are very different entities and store completely different data. Hope that makes sense?
Phil
Maybe like: Component = food_catering, EventSource = Hotel
Damir Sudarevic
The problem with that model is that you can only have 1 component for an event, when in actual fact you could have 5 components for a single event of different types (air, hotel, supplier) and each of those will be for a different component type (e.g Hotel supplying Room hire, Catering supplier providing lunch services, flights, hotel rooms etc.). I like the use of the EventSource table acting as a facade to the actual components but I am still trying to work out my initial problem of how a Supplier can be either a supplier or a hotel and how I should go about storing this relationship.
Phil
I think that I do not understand the definition of an Event. In this model, one event has a single source and a single component. A complex event (event group) is used to bring those together.
Damir Sudarevic
Sorry Damir my model wasn't particularly clear and a tad confusing. The event itself is just the basic settings of an event such as the date, venue, number of attendees, city, organiser, company etc. The components for an event would be the flights, hotels, and other supplier services that make up that event. So I have it all working fine except for a single rule from the client whereby an Event supplier can be either from the Suppliers table or from the Hotels table. So basically a Hotel could act as a supplier in some cases e.g Catering, Conference Room hire.
Phil
In addition to the Hotel being a standard component as well for providing accommodation for the event attendees. So essentially my question would be, is it better practice to store multiple foreign keys in a single table with a contraint so that one always has to exist but never both. Or should i use an arbitrary foreign key that could point to either the suppliers or hotel table which i think is an exclusive arc relationship?
Phil
A: 

A good way to test your solution is to think about what would happen if an airline became a supplier. Does your solution handle that or start to get complicated.

Why do you explicitly need to find hotel data down the supplier route if you don't need that level of data other types of supplier? I would suggest that a supplier is a supplier, whether its a hotel or not for these purposes.

If you want to flag a supplier as a hotel, then simply put hotelid on the supplier table or else wait and hook in the supplier later via whatever mechanism you use to get detail on other suppliers.

dwarFish