我有三张桌子:
Modules
| ID | name |
Subscription
| module_id | user_id | ...
User
| ID | user_name |
我需要一个唯一订阅集列表。 (即x用户订阅模块(1),y用户订阅(1,2)等。我可以在SQL中执行此操作吗?
答案 0 :(得分:0)
让我们设置一些表格。
create table modules (
module_id integer not null,
module_name varchar(15) not null,
primary key (module_id),
unique (module_name)
);
insert into modules values (1, 'First module');
insert into modules values (2, 'Second module');
create table users (
user_id integer not null,
user_name varchar(15) not null,
primary key (user_id),
unique (user_name)
);
insert into users values (100, 'First user');
insert into users values (101, 'Second user');
create table subscriptions (
module_id integer not null,
user_id integer not null,
primary key (module_id, user_id),
foreign key (module_id)
references modules (module_id),
foreign key (user_id)
references users (user_id)
);
insert into subscriptions values (1, 100);
insert into subscriptions values (1, 101);
insert into subscriptions values (2, 100);
要获得正确的计数,您只需要对表格进行查询"订阅"。
select module_id, count(*) as num_users
from subscriptions
group by module_id
order by module_id;
module_id num_users -- 1 2 2 1
您可以在联接中使用该语句来获取模块名称而不是模块ID号。
select t1.module_name, t2.num_users
from modules t1
inner join (select module_id, count(*) as num_users
from subscriptions
group by module_id
) t2
on t1.module_id = t2.module_id
order by t1.module_name;
module_name num_users -- First module 2 Second module 1
您需要使用Innodb引擎来强制执行外键约束。
要获得订阅了模块ID 1和2的用户,请使用WHERE子句选择模块ID号,使用GROUP BY子句获取计数,并使用HAVING子句将输出限制为仅那些计数为2的用户ID号。(这意味着他们已经在WHERE子句中订阅两者那些模块。)
select user_id, count(*) num_modules
from subscriptions
where module_id in (1, 2)
group by user_id
having count(*) = 2;
如果您需要报告所有可能的模块组合,这种要求会很快爆发。仅10个模块,有超过1000种可能的组合。通常,您希望将程序编写到
答案 1 :(得分:0)
我的同事提出了一个有趣的解决方案
select module_combinations
from (select user_id, group_concat(module_id separator ', ') as module_combinations from subscriptions group by user_id) a
group by a.module_combinations
但这似乎更接近回答原来的问题。
select module_combinations, count(*) as num_users
from (select group_concat(module_id order by module_id) as module_combinations
from subscriptions
group by user_id) a
group by a.module_combinations;