从值子集中选择多个最小值

时间:2016-08-23 08:39:23

标签: mysql database join

我正在创建一个访问系统。访问系统基于用户可以是多个组的成员,该域是用户请求访问的位置。例如,用户可以是两个组的成员,这两个组都可以访问域,并且用户可以是域的成员。我希望最低访问权限是有效权限,假设您被添加到该域中右下方应该在另一个权限之前的权限的组中。

问题是我想选择每个域并获得每个域的所有访问权限。 所以问题是从多个子集中选择最小值。知道如何做到这一点?

所以我尝试过:

SELECT r.* FROM `domain` as d 
INNER JOIN ( 
    SELECT domain, min(`update`) FROM `right` 
    ) r ON d.name = r.domain;

这给了我结果:

域min(update

另一个测试是真的

我想要的是:

域min(update

另一个测试是真的

有些名字是真的

Sql小提琴链接:http://sqlfiddle.com/#!9/841183

使用测试值导出sql表:

CREATE TABLE `domain` (
  `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `displayName` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `description` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

ALTER TABLE `domain`
  ADD PRIMARY KEY (`name`);

CREATE TABLE `groups` (
  `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `created_by` varchar(32) COLLATE utf8_unicode_ci DEFAULT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

ALTER TABLE `groups`
  ADD PRIMARY KEY (`name`),
  ADD KEY `groups_created_by_foreign` (`created_by`);


CREATE TABLE `right` (
  `domain` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `group` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `read` tinyint(1) NOT NULL,
  `update` tinyint(1) NOT NULL,
  `create` tinyint(1) NOT NULL,
  `delete` tinyint(1) NOT NULL,
  `modify` tinyint(1) NOT NULL,
  `execute` tinyint(1) NOT NULL,
  `created_by` varchar(32) COLLATE utf8_unicode_ci DEFAULT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

ALTER TABLE `right`
  ADD PRIMARY KEY (`domain`,`group`),
  ADD KEY `right_group_foreign` (`group`),
  ADD KEY `right_created_by_foreign` (`created_by`);


INSERT INTO `domain` (`name`, `displayName`, `description`, `created_at`, `updated_at`) VALUES
('Another test', 'Another test', NULL, '2016-08-22 12:05:06', '2016-08-22 12:05:06'),
('Some Name', 'Some Name', NULL, '2016-08-19 03:57:00', '2016-08-19 03:57:00');


INSERT INTO `groups` (`name`, `created_by`, `created_at`, `updated_at`) VALUES
('groupTest', NULL, '2016-08-22 12:06:48', '2016-08-22 12:06:48'),
('testGroup', NULL, '2016-08-19 03:56:35', '2016-08-19 03:56:35');


INSERT INTO `right` (`domain`, `group`, `read`, `update`, `create`, `delete`, `modify`, `execute`, `created_by`, `created_at`, `updated_at`) VALUES
('Another test', 'groupTest', 0, 1, 0, 0, 0, 0, NULL, '2016-08-22 12:07:02', '2016-08-22 12:07:02'),
('Another test', 'TestGroup', 1, 1, 0, 0, 0, 0, NULL, '2016-08-22 12:06:04', '2016-08-22 12:06:04'),
('Some Name', 'TestGroup', 0, 1, 0, 0, 0, 0, NULL, '2016-08-19 03:57:05', '2016-08-19 03:57:05');

1 个答案:

答案 0 :(得分:1)

您需要使用group by子句按组获取最小值。这里的群组我指的是域名:

select d.name, min(`update`) as min_update_right
from domain d
inner join `right` r on d.name = r.domain
group by d.name

如果您希望域表中的其他字段出现在选择列表中,那么您还需要将这些字段添加到分组列表中。

但是,我会考虑使用位图(或在MySQL中使用set数据类型)而不是多个字段来存储访问权限。简单的按位操作可以为您提供对域的整体访问权限。