2

I have a scenario and i'm confused about how i can go about designing the database schema for it.

In my software (php) there are companies and applications.

companies need to have licenses to access applications.

now the fields (for form while purchasing licenses) for each application is different.

for ex:

for application1:

fields are:

  1. no of users
  2. no of groups

for application2:

  1. no of users

for application3:

  1. number of hours of usage

Prices are based on these fields.

Now i need to design schema for this so that on one page company can manage licenses for all applications.

How can i make this schema generic?

Please help. Thanks.

Meherzad
  • 8,433
  • 1
  • 30
  • 40
david
  • 122
  • 3
  • 11

5 Answers5

1

You can go with this type of structure

select * from applicationMaster



| APPID |      APPNAME |
------------------------
|     1 | Application1 |
|     2 | Application2 |

ApplicationMaster will go with main Application related details which won't be repeated such Name, date etc.

Query 2:

select * from applicationField



| FIELDID | APPID |   FIELDNAME |
---------------------------------
|       1 |     1 |   NoOfUsers |
|       2 |     1 |  NoOfGroups |
|       3 |     2 | NoHourusage |

ApplicationField can adjust any number of field for a particular appId. So AppId 1 has 2 fields NoofUsers and NoOfGroups. It is also capable to adjust newer fields for a particular app if you want.

Query 3:

ApplicationValue will have the values for every license aplication so it will have compId which represents which company has applied using fieldId which refers to applicationField table we can get for which app values are stored.

select * from applicationValue



| ID | COMPID | FIELDID | FIELDVALUE |
--------------------------------------
|  1 |      1 |       1 |         50 |
|  2 |      1 |       2 |        150 |
|  3 |      2 |       3 |        350 |
|  4 |      3 |       1 |        450 |
|  5 |      3 |       2 |         50 |

applicationPriceMaster stores the price package for each application. There could be multiple package for a application.

select * from applicationPriceMaster


| APPPACKAGE | APPID | TOTALPRICE |
-----------------------------------
|          1 |     1 |         50 |
|          2 |     1 |        100 |

For each application package its details will posted in this table.

select * from applicationPriceDetail


| APPPACKAGE | FIELDID | QUANT |
--------------------------------
|          1 |       1 |     1 |
|          1 |       2 |     1 |
|          2 |       1 |    10 |
|          2 |       2 |     1 |

NOTE Please check the structure as it is now too complex and check what type of queries you would be running on these table and its performance.

select apm.APPPACKAGE, TOTALPRICE from
applicationPriceMaster apm
inner join 
(select APPPACKAGE from applicationPriceDetail
where FIELDID=1 and QUANT=1)a
on apm.APPPACKAGE = a.APPPACKAGE
inner join
(select APPPACKAGE from applicationPriceDetail
where FIELDID=2 and QUANT=1)b
on 
a.APPPACKAGE=b.APPPACKAGE

SQL FIDDLE:

| APPPACKAGE | TOTALPRICE |
---------------------------
|          1 |         50 |

For single filter you have to use this query, so you have to increase number of inner query with the number of inner filter.

select apm.APPPACKAGE, TOTALPRICE from
applicationPriceMaster apm
inner join 
(select APPPACKAGE from applicationPriceDetail
where FIELDID=1 and QUANT=1)a
on apm.APPPACKAGE = a.APPPACKAGE

NOTE-This query is quite complex and will only work if the values are same as mentioned in the packagedetail table and will work only if the values are 2 filter you have to remove 1 inner join if there is only 1 filter. So I suggest you to reconsider before using this approach.

Meherzad
  • 8,433
  • 1
  • 30
  • 40
  • Thanks @Meherzad This is good. I am able to get this till here. There is one more problem. License price for application1 is based on no of users and no of groups. For example: 1 user + 1 group - $50 10 user + 1 group - $100 So, when i show the payment form to the company , i need to show select boxes for no of users and no of groups since they are fixed values. how can design the schema to accomodate that? – david May 15 '13 at 06:03
  • The prices are not fixed and for individual fieldType? If they are fixed you can add an extra column in the `applicationField` table which fixes price for a particular column EX 1 User cost is 5 so accordingly it will be calculated. If not then you need to create `package` table which stores the package. I am adding that table in the answer check the edit. – Meherzad May 15 '13 at 06:10
  • 1
    Thanks! Problem is: price is based on combination of fields like Noofusers+noofgroups! What do you think? – david May 15 '13 at 06:12
  • In General you should try avoiding having a Key/Value Tables. – Borik May 15 '13 at 06:13
  • Btw i should store the price too somewhere. :( Becoming too complex, i think – david May 15 '13 at 06:15
  • @Borik the main reason for going for this key/value approach is because the number of fields are not constant. Can you please suggest any solution for this?? – Meherzad May 15 '13 at 06:24
  • @Meherzad thanks a lot! This is really good. The type of queries i will be running: When company selects application, i need to show them a form (i'll take example of application1). Form ----- Select no of users : dropdown Select no of groups : dropdown After selection get the price and go for payment. This is how i want it. What do you thin? – david May 15 '13 at 06:27
  • @Borik Thanks but it doesn't look like there's another way. – david May 15 '13 at 06:28
  • @Meherzad this [topic](http://stackoverflow.com/questions/126271/key-value-pairs-in-relational-database) been covered, but i don't think that this app will very big fluctuation in fields... – Borik May 15 '13 at 06:30
  • @Meherzad I don't find many drawbacks here. I think it solves my puzzle. – david May 15 '13 at 06:50
  • @Meherzad I need to run two queries here: While showing purchase form: (i'll take example of application1). Form ----- Select no of users : dropdown Select no of groups : dropdown After selection get the price and go for payment. And another query is to get price from no of users and no of groups. Ofcourse this is different for each application. – david May 15 '13 at 06:52
  • @Meherzad Please let me know what you think. Thanks – david May 15 '13 at 06:53
  • @david It is becoming to complex to create this query. If you don't think this solves your problem then you can remove my answer as accepted answer. – Meherzad May 15 '13 at 07:33
  • If you have price in such manner it would easy to manage and query also EX NoOfUser you can add 1 column which gives per user price so we can calculate the price accordingly from the user chosen values. Alternatively you directly give user the option of giving the whole package as option so removing the table `applicationPriceDetail` will remove the complexity of the whole structure. Hope it helps... – Meherzad May 15 '13 at 07:51
1

What you have there, could be easily mapped to Classes in an OO language (like PHP). You have an Abstract License, and then 3 Subclasses (ApplicationByUsersAndGroups, etc). Then, mapping to a Relational database is a very common problem, here is a nice article about it: http://www.ibm.com/developerworks/library/ws-mapping-to-rdb/

It has 3 options, it depends on the way you want to structure your application which one you should use. I recommend reading it, it is not that long.

Alex Siri
  • 2,856
  • 1
  • 19
  • 24
0

how about a table structured this way:

LicenseId int  PK
CompanyId Int  PK 
AppId     Int  PK
LicenseType int
NumberOfUsers int
NumberOfGroups int
NumberOfHours int
Price    Money

Depending on LicenseType, you will use different column in your business logic, you might need to add CompanyID and/or AppID, that depends how you going to structure those tables as well as relation ships between company/app/license.

Some questions to think about:

  • Can one company have different License Types for same App?
  • Can one company have different Apps?
Borik
  • 438
  • 3
  • 9
  • Thanks! So you are saying, one table would be sufficient. But if the fields: NumberOfUsers int NumberOfGroups int NumberOfHours int
    are columns of a table, how can i go about adding applications to my software later, then i will have to add a new column right? Also, this table isn't normalized right?
    – david May 15 '13 at 05:57
  • Yes you might want to add an ApplicationID and/or CompanyID directly to a table or create and Reference Table that will have columns ApplicationID, LicenseID, CompanyID, all depends on your needs. If relation ship is 1 to 1 then you can get away without using reference Table. – Borik May 15 '13 at 06:05
  • Its Normalized, you can add LicenseType Table, as FK constrained , or you can do simple Static Values constrained. – Borik May 15 '13 at 06:13
  • Thanks, but i will need to show the form to company with fields as i described in another comment on Meherzad's reply. – david May 15 '13 at 06:32
  • Don't mix the presentation logic, with data structure, you have here one row per company/app license, that covers all your requirements. – Borik May 15 '13 at 06:38
0

One way is

Table LICENCES:
LICENSE_ID ==> UNIQUE IDENTIFIER
COMPANY_ID ==> references table COMPANIES
APPLICATION_ID ==> references table APPLICATIONS
LICENCE_TYPE ==> either of "BY_GROUPS_AND_USERS", "BY_USERS", "BY_HOURS"
LICENCE_BODY_ID ==> ID of specific body table
[...]

Table LIC_TYPE_BY_GROUPS_AND_USERS: 
LICENCE_BODY_ID ==> body identifier
NO_GROUP 
NO_USERS
[...]

Table LIC_TYPE_BY_USERS: 
LICENCE_BODY_ID ==> body identifier
NO_USERS
[...]

This way, your intention is clear. Even after long time comming back, you will know in no time how things are organized, which fields are used in which case...

igr
  • 3,409
  • 1
  • 20
  • 25
  • Thanks @igr But do i need to have different tables for different license types? – david May 15 '13 at 06:05
  • Just added comment about it. You don't have to. It will depend on number of different options you can have in each table and how that would evoluate. My answer went in sense of easier "mental parsing", easier to reason about. Imagine if you had tens or more options that are used in some cases, other in others. But, nobody can know better your context, so take what makes sense for you. – igr May 15 '13 at 06:08
0

Dont complicate things, if the number of users is unlimited then set it to 999999 or some other max value.

This keeps the license check logic (which will run every time a user logs in ) simple and the same for all applications.

You will need extra logic in the licenses maintenance application, but this should also be pretty simple: if the cost_per_user is = 0 then set no_of_users = 99999

Again you end up with the same licensing screen and logic for all your applications.

James Anderson
  • 27,109
  • 7
  • 50
  • 78