【问题标题】:Join on multiple tables where table column has mixed values加入多个表,其中表列具有混合值
【发布时间】:2014-08-18 11:29:06
【问题描述】:

大家好!在过去的几天里,我一直在网上和 SO 上寻找解决方案。这是我的第一个问题,所以请耐心等待:)

在解释之前,如果它太简单了,我想道歉,但我已经尝试了我能想到的一切,但我一无所获。所以,让我们开始吧:)

问题是在 t3_access.auth_id 中有 user_id 和 group_id 之类的值,所以我需要编写一个查询来列出 t3_access.auth_id 列中列出的所有用户以及组后面的用户t3_access.auth_id。

在某些查询中甚至可以区分与 user_id 或 group_id 连接的用户吗?任何帮助都非常受欢迎。

这里是 sqlfiddle 链接:http://sqlfiddle.com/#!2/b6dd7/5

我有四个表及其结构:

t1_users (user_id, name, pwd_opts)
t2_connections (user_id, group_id, conn_opts)
t3_access (auth_id, class_name, gr_name)
t4_groups (group_id, group_name)

这里是示例数据:

create table t1_users ("user_id" varchar2(10), "name" varchar2(10), "pwd_opts" varchar2(10));
create table t2_connections ("user_id" varchar2(10), "group_id" varchar2(10), "conn_opts" varchar2(10));
create table t3_access ("auth_id" varchar2(10), "class_name" varchar2(10), "gr_name" varchar2(10), "access" varchar2(10));

create table t4_groups ("GROUP_ID" varchar2(10), "group_name" varchar2(20));

insert into t1_users ("user_id", "name", "pwd_opts", "usr_opts") values ('Peter','Peter Pan','OK','RESTRICTED');
insert into t1_users ("user_id", "name", "pwd_opts", "usr_opts") values ('George','George Michael','OK','NORMAL');
insert into t1_users ("user_id", "name", "pwd_opts", "usr_opts") values ('Danny','Danny Boy','LOCK','SPECIAL');
insert into t1_users ("user_id", "name", "pwd_opts", "usr_opts") values ('John','John Wayne','OK','NORMAL');


insert into t2_connections (user_id, group_id, conn_opts) values('Peter','GROUP1','NORMAL');
insert into t2_connections (user_id, group_id, conn_opts) values('Peter','GROUP2','NORMAL');
insert into t2_connections (user_id, group_id, conn_opts) values('George','GROUP2','SPECIAL');
insert into t2_connections (user_id, group_id, conn_opts) values('Danny','GROUP2','NORMAL');
insert into t2_connections (user_id, group_id, conn_opts) values('John','GROUP3','NORMAL');


insert into t3_access(auth_id, class_name, gr_name, access) values('Peter','class1','PROFILE1','READ');
insert into t3_access(auth_id, class_name, gr_name, access) values('GROUP2','class1','PROFILE2','READ');
insert into t3_access(auth_id, class_name, gr_name, access) values('GROUP3','class3','PROFILE3','UPDATE');
insert into t3_access(auth_id, class_name, gr_name, access) values('George','class2','PROFILE2','EXECUTE');
insert into t3_access(auth_id, class_name, gr_name, access) values('John','class4','PROFILE4','NONE');

insert into t4_groups (group_id, "group_name") VALUES ('GROUP1', 'first group');
insert into t4_groups (group_id, "group_name") VALUES ('GROUP2', 'second group');
insert into t4_groups (group_id, "group_name") VALUES ('GROUP3', 'third group');

我已经尝试过(我在两个选择之间尝试过 UNION、IN、EXISTS),但没有得到预期的结果:

select t2_connections.*, t3_access.*
from t2_connections
join t3_access ON t2_connections.group_id = t3_access.auth_id 
where group_id IN (select auth_id from t3_access where auth_id like 'GROUP%');

select t2_connections.*, t3_access.*
from t3_access
join t2_connections ON t3_access.auth_id = t2_connections.user_id
where auth_id IN (select auth_id from t3_access where user_id like 'George' or auth_id like 'Danny' or auth_id like 'Peter' or auth_id like 'John' );

...我也试过了:

select t1_users.user_id, t1_users.name, t1_users.pwd_opts, t1_users.usr_opts,
       t2_connections.group_id, t2_connections.conn_opts, t3_access.class_name, t3_access.gr_name,
       t3_access.access
from t2_connections
join t1_users on t2_connections.user_id = t1_users.user_id
join t4_groups on t2_connections.group_id = t4_groups.group_id
join t3_access on t2_connections.group_id = t3_access.auth_id
where exists (select * from t3_access where t3_access.auth_id = t2_connections.user_id);
union 
select t1_users.user_id, t1_users.name, t1_users.pwd_opts, t1_users.usr_opts,
       t2_connections.group_id, t2_connections.conn_opts, t3_access.class_name, t3_access.gr_name,
       t3_access.access
from t2_connections
join t1_users on t2_connections.user_id = t1_users.user_id
join t4_groups on t2_connections.group_id = t4_groups.group_id
join t3_access on t2_connections.group_id = t3_access.auth_id
where exists (select * from t3_access where t3_access.auth_id = t2_connections.group_id);

预期的输出应该是这样的:

user_id|name |pwd_|usr_opts    |group_id|conn_opt|cl_name |gr_name   |access
Peter | bla1 | ok | restricted | group1 | normal | class1 | profile1 | read
Peter | bla1 | ok | restricted | group2 | normal | class1 | profile2 | read
George| bla3 | ok | normal     | group2 | special| class2 | profile2 | execute
George| bla3 | ok | normal     | group2 | special| class1 | profile2 | read
Danny | bla4 |lock| special    | group2 | normal | class1 | profile2 | read
John  | bla5 | ok | normal     | group2 | normal | class4 | profile4 | none
John  | bla5 | ok | noraml     | group3 | normal | class3 | profile3 | update

【问题讨论】:

  • 如果您提出问题,我们可能会为您提供帮助。
  • 第一次发帖,不习惯编辑器...不能很好的格式
  • 您的示例不起作用。某些列不存在,某些列数据超出列宽,某些列名大小写不匹配。

标签: sql join oracle11g


【解决方案1】:

将您的示例设置修改如下...

create table t1_users (user_id varchar2(10), name varchar2(20), pwd_opts varchar2(10), usr_opts varchar2(15));
create table t2_connections (user_id varchar2(10), group_id varchar2(10), conn_opts varchar2(10));
create table t3_access (auth_id varchar2(10), class_name varchar2(10), gr_name varchar2(10), acces varchar2(10));
create table t4_groups (group_id varchar2(10), group_name varchar2(20));

insert into t1_users (user_id, name, pwd_opts, usr_opts) values ('Peter','Peter Pan','OK','RESTRICTED');
insert into t1_users (user_id, name, pwd_opts, usr_opts) values ('George','George Michael','OK','NORMAL');
insert into t1_users (user_id, name, pwd_opts, usr_opts) values ('Danny','Danny Boy','LOCK','SPECIAL');
insert into t1_users (user_id, name, pwd_opts, usr_opts) values ('John','John Wayne','OK','NORMAL');

insert into t2_connections (user_id, group_id, conn_opts) values('Peter','GROUP1','NORMAL');
insert into t2_connections (user_id, group_id, conn_opts) values('Peter','GROUP2','NORMAL');
insert into t2_connections (user_id, group_id, conn_opts) values('George','GROUP2','SPECIAL');
insert into t2_connections (user_id, group_id, conn_opts) values('Danny','GROUP2','NORMAL');
insert into t2_connections (user_id, group_id, conn_opts) values('John','GROUP3','NORMAL');

insert into t3_access(auth_id, class_name, gr_name, acces) values('Peter','class1','PROFILE1','READ');
insert into t3_access(auth_id, class_name, gr_name, acces) values('GROUP2','class1','PROFILE2','READ');
insert into t3_access(auth_id, class_name, gr_name, acces) values('GROUP3','class3','PROFILE3','UPDATE');
insert into t3_access(auth_id, class_name, gr_name, acces) values('George','class2','PROFILE2','EXECUTE');
insert into t3_access(auth_id, class_name, gr_name, acces) values('John','class4','PROFILE4','NONE');

insert into t4_groups (group_id, group_name) VALUES ('GROUP1', 'first group');
insert into t4_groups (group_id, group_name) VALUES ('GROUP2', 'second group');
insert into t4_groups (group_id, group_name) VALUES ('GROUP3', 'third group');

commit;

我能得到的最接近你需要的是:

with all_users$ as (
    select
        U.user_id, U.name, U.pwd_opts, U.usr_opts, C.group_id, C.conn_opts, A.class_name, A.gr_name, A.acces
    from t3_access A
        join t1_users U on U.user_id = A.auth_id
        join t2_connections C on C.user_id = A.auth_id
),
all_groups$ as (
    select
        U.user_id, U.name, U.pwd_opts, U.usr_opts, C.group_id, C.conn_opts, A.class_name, A.gr_name, A.acces
    from t3_access A
        join t2_connections C on C.group_id = A.auth_id
        join t1_users U on U.user_id = C.user_id
    where exists (
            select 1
            from t4_groups G
            where G.group_id = A.auth_id
        )
)
select *
from all_users$ AU
where not exists (
        select 1
        from all_groups$ Gx
        where Gx.user_id = AU.user_id
            and Gx.group_id = AU.group_id
            and Gx.class_name = AU.class_name
    )
--
union all
--
select *
from all_groups$ AG
;

【讨论】:

  • 结果应该像我在帖子的示例输出中指定的那样,问题是在您的查询中有一些空值,不应该有任何空值。我知道设计很糟糕......
  • 你不懂。我看到我的查询结果中有 NULL。我在问:为什么不应该有 NULLs ?用准确准确的英文句子描述你想要达到的目标。
  • 因为它是一个记录用户连接的系统。这样,用户就可以使用他的 user_id 或他的 group_id 进行连接。我需要获取用户与他的 user_id 连接的记录,如果他与他的 group_id 连接,那么查询应该返回属于 t3.auth_id 列中的组的所有用户(group2 和 group3 用户)。因此查询应该返回与其 user_id 连接的用户和隐藏在 group_id 后面的用户。对不起,如果我不够清楚。如果这种设计无法做到这一点,是否可以改变设计以实现这种查询?
  • 没问题。对我来说是一次心理锻炼。 :-) 好的,我根据您的规范更新了我的答案。查询仍然没有返回您需要的内容。你确定你知道你需要什么吗?
  • 可能由于设计不佳而无法实现...我需要获取连接到目标数据库的所有用户连接。无论他是用他的 id 还是他的 group_id 连接的,所以结果应该列出所有 user_id-s。这是一项奇怪的任务,因为我无权访问数据模型,但他的模型可以更改,但我不知道如何实现这一点......感谢您的努力
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-17
  • 2010-12-03
  • 2012-10-20
  • 2021-11-28
  • 1970-01-01
  • 2014-05-12
  • 1970-01-01
相关资源
最近更新 更多