sql—如何基于mysql中不同维度的用户访问限制对事实的访问

c3frrgcw  于 2021-07-27  发布在  Java
关注(0)|答案(1)|浏览(300)

概述
我正在使用mysql5.7,我有一个模型,我需要能够确定健身房的位置,每个成员都可以访问。这些会员可以根据每个地点的属性(如其上级健身房、附属机构等)访问一个或多个健身房。例如,作为一名会员,我可能能够访问一个特定的地点,因为我是该健身房母公司的会员(例如,作为planet fitness的会员,我可以访问所有planet fitness地点),或者我可以访问我的雇主支付的特定planet fitness地点。对于这个人为的例子,我们可以说每个位置与每个父属性都有1:1的关系。
位置是星型架构中的事实表,访问定义的级别(例如由健身房、医疗保健提供商)是该事实表的维度。我在下面加入了sql,用这些场景来设置一个db,并想知道什么(如果有的话)模型或模式非常适合描述这种关系。
erd示例
期望的结果
假设我们有两个成员,比尔和特德。比尔是axiom的成员,微软的雇员和蓝十字会的成员。泰德是“星球健身”的会员。
鉴于这些记录:

-----------------------------------------------------------------------------
| location_id   |   gym_name       |    company_name    |   provider_name   |
-----------------------------------------------------------------------------
| 1             |   Planet Fitness |    NULL            |   NULL            |
| 2             |   Planet Fitness |    Microsoft       |   NULL            |
| 3             |   Planet Fitness |    NULL            |   Blue Cross      |
| 4             |   Planet Fitness |    Microsoft       |   Blue Cross      |
| 5             |   Axiom          |    NULL            |   NULL            |
| 6             |   Axiom          |    NULL            |   Blue Cross      |
| 7             |   Axiom          |    Microsoft       |   Blue Cross      |
-----------------------------------------------------------------------------

我想做一些事情,比如:

SELECT loc.*
FROM locations loc
JOIN member_access USING (gym_id)
WHERE member_id = ?

为比尔或泰德准备一份独特的地点清单。我希望:
bill可以访问六个地点(三个axiom地点+三个planet fitness地点,允许microsoft员工和/或blue cross成员访问)
ted可以访问四个地点(带有planet fitness gym\u名称的地点)
我试过的东西
存储间隔user:gym relationship 但是这个表太大了(十亿条记录),而且数据的波动太大,无法满足sla的要求。
维护单独的表user:gyms, user:providers, user:companies relationships,但结果必须是这些值的联合(即,根据我的健身房会员资格,我可以访问的所有唯一位置+我的公司允许我访问的所有位置+我的医疗保健提供商允许我访问的所有位置)。提供此可用位置列表的响应已分页,因此我不希望每次需要返回~20页时都要合并数千条记录。
示例数据库

drop database if exists so_gyms;
create database so_gyms;
use so_gyms;

CREATE TABLE members (
    member_id smallint not null auto_increment
    , member_name varchar(64)
    , PRIMARY KEY (member_id)
);

CREATE TABLE gyms (
    gym_id smallint not null auto_increment
    , gym_name varchar(64)
    , PRIMARY KEY (gym_id)
);

CREATE TABLE companies (
    company_id smallint not null auto_increment
    , company_name varchar(64)
    , PRIMARY KEY (company_id)
);

CREATE TABLE providers (
    provider_id smallint not null auto_increment
    , provider_name varchar(64)
    , PRIMARY KEY (provider_id)
);

CREATE TABLE locations (
    location_id smallint not null auto_increment
    , gym_id smallint
    , company_id smallint
    , provider_id smallint

    , PRIMARY KEY (location_id)
    , FOREIGN KEY (gym_id) REFERENCES gyms (gym_id)
    , FOREIGN KEY (company_id) REFERENCES companies (company_id)
    , FOREIGN KEY (provider_id) REFERENCES providers (provider_id)
);

INSERT INTO members (member_name) VALUES ('Bill'), ('Ted');
INSERT INTO gyms (gym_name) VALUES ('Planet Fitness'), ('Axiom');
INSERT INTO companies (company_name) VALUES ('Microsoft');
INSERT INTO providers (provider_name) VALUES ('Blue Cross');
INSERT INTO locations (gym_id, company_id, provider_id) VALUES
(1, null, null), # a Planet Fitness location
(1, 1, null), # a Planet Fitness location w/ Microsoft access (pun unintended)
(1, null, 1), # a Planet Fitness location w/ access for Blue Cross members
(1, 1, 1), # a Planet Fitness location w/ access for MS employees & Blue Cross members
(2, null, null), # an Axiom location
(2, null, 1), # an Axiom location w/ access for Blue Cross members
(2, 1, 1); # an Axiom location w/ access for MS employees & Blue Cross members
vmpqdwk3

vmpqdwk31#

澄清一下,您是在尝试构建一组表来回答这个特定的问题,还是在尝试构建一个通用的星型模式来回答这个问题和其他类似的问题?
如果你只想回答这一个问题,那么我会用3nf构建一组表,类似于:user 1:m company 1:m gym,为了让生活更轻松,在company表中为每个gym添加一个虚拟记录,这样无论用户是直接链接到gym还是通过company链接,你都有相同的层次结构。
如果您想设计一个星型模式,那么您需要确定事实表度量和粒度是什么,然后从中构建设计。如果您有一个正确设计的星型模式,并且最终有数十亿条记录(这是很容易做到的),那么如果您的dbms或etl不能处理它,那么这似乎是您的工具选择(或者可能是它的实现/配置)的问题

相关问题