Question
1) I'm looking for an appropriate way to design a web application, and specifically the database schema, so that I can have a base table with all the core fields for a given service, and then depending on the type of service, I will need an additional set of fields to be associated with the service.
I need to do this in such a way that performing searches will be straight forward and offer reasonable performance. I'm probably looking at some type of full-text searching, but would only have 5 concurrent users of the application, at most.
My end goal for the application is to be able to pretty much search the entire database for any given keyword and return all related records. I was initially looking to split out the set fields for each service type into separate tables with their own columns, but I'm thinking that in doing so it might lead to more complicated search queries (Many JOINs) or many more queries to be run per search.
For any solution proposed, can you please specify why you think this would be a good fit?
2) My other issue (as will hopefully become clear below) is that my design currently consists of a "service types" table where I would define the core types of each product, where each service is then an "instance" of a given product.
My issue here is that it feels like I'll probably end up most duplicating things if I have both a products and a service types table. So to avoid this duplication is the other main thing I'm trying to achieve in my design.
More Details
I'm currently writing a custom web application used to track the services provisioned on a per-customer basis, not only for invoicing (billing cycle, start/end date, price) but also for documentation of those services (associated user accounts, IP addresses, physical assets, etc).
Each service is based off a "product" table which defines the name of a base product, the price, billing duration, description, etc... We could have multiple products of the same type (eg. For different plans of a given product type). For example, we have the following products:
- Shared WebHosting Plan One
- Shared WebHosting Plan Two
- Shared WebHosting Plan Three
- Dedicated Server Plan
- Virtual Dedicated Server Plan One
- Virtual Dedicated Server Plan Two
Right now the issue I have is that, we have a number of fields which are common to any given service, but we also have a number of fields which change, depending on the "type" of service being tracked. Depending on the type of the service, I will display the base form for all services, but also the appropriate form for adding/editing etc...
For example, we have the following service types, and each product (as shown above) would relate to one of these core service types:
- Shared Web Hosting
- Dedicated Hosting
- Virtual Dedicated Hosting
- ADSL
- ...
My Possible Solutions
Current Solution - Multiple Tables
Currently, in my database, I have:
ServiceTypes
- ServiceTypeID INT PK
- Type VARCHAR(40)
Product
- ProductID INT PK
- Name VARCHAR(40)
- Description TEXT
- Price DECIMAL
- BillingDuration INT
- TypeID INT (FK ServiceTypes.ServiceTypeID)
Service
- ServiceID INT PK
- ProductID INT (FK: Product.ProductID)
- Name VARCHAR(40)
- Description TEXT
- Price DECIMAL
- BillingDuration INT
- Active BIT
- StartDate DATETIME
- EndDate DATETIME
Those are the main tables for any service, then I've got additional tables for the extended properties:
ServiceADSLInfo
- ServiceADSLInfoID INT PK
- ServiceID INT (FK: Service.ServiceID)
- FNN VARCHAR(10)
- Username VARCHAR(20)
- Password VARCHAR(20)
- LocationID INT (FK: Locations.LocationID)
- ModemAssetID INT (FK: Assets.AssetID)
ServiceVirtualServerInfo
- ServiceVirtualServerInfo INT PK
- ServiceID INT (FK: Service.ServiceID)
- ServerName VARCHAR(20)
- IPAddress INT (FK: IPAddresses.AddressID)
- HostServer INT (FK: Assets.AssetID)
- Username VARCHAR(20)
- Password VARCHAR(20)
ServiceSharedHostingInfo
- ServiceSharedHostingInfoID INT PK
- ServiceID INT (FK: Service.ServiceID)
- Hostname VARCHAR(50)
- HostServer INT (FK: Assets.AssetID)
- DiskSpaceQuota INT
- BandwidthQuota INT
Other Solution - Single Table
I'm thinking of storing all service related information in a single table, regardless of the type of service, and just have the values be NULL if they're not needed for that particular service.
- ServiceID INT PK
- ProductID INT (FK: Product.ProductID)
- Name VARCHAR(40)
- Description TEXT
- Price DECIMAL
- BillingDuration INT
- Active BIT
- StartDate DATETIME
- EndDate DATETIME
- Username VARCHAR(20)
- Password VARCHAR(20)
- FNN VARCHAR(10)
- LocationID INT (FK: Locations.LocationID)
- AssetID INT (FK: Assets.AssetID)
- ...
I feel like this might be an easier solution to work with in terms of searching as well, since in order to service any service related data, I can just use a full text search on the single table, and not worry about joining records together.
My main concern here would be that I end up with a table that has 30+ columns, which seems like it could get pretty messy. The other thing is that it doesn't solve both my concerns, because I would still need to have the core serviceTypes table to figure out which fields I need to use for any given search - and hence still have some overlap with my products table.
I'm wondering if some degree of overlap with the products table is impossible to avoid?
Entity-Attribute-Value model
I've considered this design as well. Overall, I feel like this is overkill for me as I don't need things to be that flexible and dynamic. We will need a set group of fields depending on the service type, but the data we need to collect on each core service type I can't see changing any time soon, so this can be static.
It also seems to me that the application logic needed to implement this level of flexibility would be far too complicated for the benefits it brings.
Having to determine the type of HTML form field to display depending on the type of the field queried from the database etc... Just sounds painful.
Please let me know if there are any further details I can provide! I hope everything is clear.
Thanks!