Skip to Main Content

Breadcrumb

Question and Answer

Chris Saxon

Thanks for the question, Alexandru.

Asked: September 30, 2020 - 8:50 am UTC

Last updated: September 30, 2020 - 10:00 am UTC

Version: 11.2.0.4

Viewed 1000+ times

You Asked

Hi TOM,

I need to accommodate this kind of object (subscription) in the database (not necessarily JSON):
    {
      "subscriber": 12343, --user_id
      "subscr_data_start": 20200901,
      "subscr_data_end": "",
      "object_name": "a very fancy name",
      "object_event_type": "create",
      "object_type": "product",
      "object_event_match": "exact",
      "conditions": { "countries": ["IT", "DE"], "categories": ["computers", "HI-FI"] 
      }
    }

That would translate as:
Starting from `20200901` with no end date, the user `12343` would like to be alerted every time we `create` a `product` of kind (`computers` or `HI-FI`) in either country (`IT` or `DE`) whose name matches `exact`ly `a very fancy name`.

Data modelling details in the LiveSQL link.

Is it a correct/valid approach later on when i need to query it (using `subscriber` column as index?
If not, should i go with the standard relational approach instead ?

Thanks,
Alex


with LiveSQL Test Case:

and Chris said...

When creating your tables, it's important to think through what you're going to use the data for. There are two use cases I can think of here:

- Show all the subscriptions for a particular user
- After adding a product, find all the people subscribed to it

The first requirement is easy:

select * from subscriptions
where  subscriber_id = ?;


The second is more fiddly. If you store the subscription details as JSON or a nested table, you'll need to unnest the countries and categories to join them to the products table.

Whereas with relational tables, you can just join them, e.g. :

create table products (
  product_id int generated as identity,
  product_name varchar2(100),
  product_type varchar2(30),
  country_code varchar2(2)
);

create table subscriptions ( 
    id                    number (*, 0) 
  , subscriber            number (*, 0)
  , object_name           varchar2(100)
  , object_event_type     varchar2(10)
  , object_type           varchar2(20)
  , object_event_match    varchar2(10)  
  , constraint subscriptions_pk primary key (id) 
);

create table sub_countries (
    subscription_id references subscriptions ( id )
  , country_code    varchar2(2)
  , primary key ( subscription_id, country_code )
);

create table sub_categories (
    subscription_id references subscriptions ( id )
  , category_name   varchar2(30)
  , primary key ( subscription_id, category_name )
);

select * from products p
join   sub_categories sca
on     p.product_type = sca.category_name
join   sub_countries sco
on     p.country_code = sco.country_code
join   subscriptions s
on     sco.subscription_id = s.id
and    sca.subscription_id = s.id;


So personally I'd start with regular tables. I suspect there's a lot more to this project than you've listed though. Consider everything you (know) you're going to do with these data and see how different storage formats meet these needs.

Is it a correct/valid approach later on when i need to query it (using `subscriber` column as index?

I'm not sure what you're asking here.

If not, should i go with the standard relational approach instead ?

My view is relational should be the default way to define your tables, only moving to other formats if they offer big advantages given the business requirements.

Is this answer out of date? If it is, please let us know via a Comment

More to Explore

Design

New to good database design? Check out Chris Saxon's full fundamentals class.