在一列上连接两个表,如果不可能在第二列上连接
Join two tables on one column and if not possible on second column
前言
我有两个table
CREATE TABLE `permissions` (
`id` int(11) NOT NULL,
`user` int(11) DEFAULT NULL,
`name` varchar(100) COLLATE utf8mb4_unicode_ci NULL,
`orders_and_returns` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL,
`transactions` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL,
...
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `users` (
`id` int(11) NOT NULL,
`status` int(11) NOT NULL,
`access_level` int(11) NOT NULL,
`name` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`email` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
...
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
权限table有两种行,一种是配置文件
INSERT INTO permissions (`id`, `user`, `name`, `orders_and_returns`) VALUES (1, NULL, 'Admin', 1);
这意味着有一个名为 Admin 的配置文件,它授予查看订单的权限。 access_level = 1
的任何用户都是管理员,可以查看订单。
table还有第二种行
INSERT INTO permissions (`id`, `user`, `name`, `orders_and_returns`) VALUES (2, 2, NULL, 0);
这是用户特定的权限。用户 (id = 2
) 可能有 access_level = 1
,但此用户有一个覆盖,可撤销对订单的访问权限。这是必须用于确定其权限的行。
问题
我需要加载 table 中所有用户的权限。因此,当我加入用户权限 table 时,我基本上想看看我是否可以加入 users.id = permissions.user
(意味着存在用户特定覆盖),如果不能,我想加入 users.access_level = permissions.id
.我不确定该怎么做。
可能有如下两个查询,但排除了第一个查询中第二个查询的所有结果
1. SELECT email FROM users u JOIN permissions p ON u.id = p.user
2. SELECT email FROM users u JOIN permissions p ON u.access_level = p.id
2022-03-20 更新
hank will also have access_level = 1 meaning the profile is admin. But there is an override for it. The access_level value is not changed in the users table. With that change, your query returns 2 results for hank ; the profile and the override.
如果记录同时具有配置文件和 access_level,您需要首先对结果进行排名(首先通过覆盖)然后 return 仅第一个结果:
WITH cte AS(
SELECT
email
, IF(u.id = p.user
, 'user specific override'
, 'profile'
) AS PermissionType
, ROW_NUMBER() OVER(
PARTITION BY u.id
ORDER BY IF(u.id = p.user, 0, 1)
) AS RowNum
FROM users u
INNER JOIN permissions p ON u.id = p.user OR u.access_level = p.id
)
SELECT *
FROM. cte
WHERE RowNum = 1
结果:
email | PermissionType | RowNum
:-------------- | :--------------------- | -----:
john@examle.com | profile | 1
hank@examle.com | user specific override | 1
db<>fiddle here
原答案
你试过简单的 OR
SELECT email, IF(u.id = p.user, 'user specific override', 'profile')
FROM users u
INNER JOIN permissions p ON u.id = p.user OR u.access_level = p.id
结果:
email | IF(u.id = p.user, 'user specific override', 'profile')
:-------------- | :-----------------------------------------------------
john@examle.com | profile
hank@examle.com | user specific override
db<>fiddle here
前言
我有两个table
CREATE TABLE `permissions` (
`id` int(11) NOT NULL,
`user` int(11) DEFAULT NULL,
`name` varchar(100) COLLATE utf8mb4_unicode_ci NULL,
`orders_and_returns` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL,
`transactions` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL,
...
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `users` (
`id` int(11) NOT NULL,
`status` int(11) NOT NULL,
`access_level` int(11) NOT NULL,
`name` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`email` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
...
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
权限table有两种行,一种是配置文件
INSERT INTO permissions (`id`, `user`, `name`, `orders_and_returns`) VALUES (1, NULL, 'Admin', 1);
这意味着有一个名为 Admin 的配置文件,它授予查看订单的权限。 access_level = 1
的任何用户都是管理员,可以查看订单。
table还有第二种行
INSERT INTO permissions (`id`, `user`, `name`, `orders_and_returns`) VALUES (2, 2, NULL, 0);
这是用户特定的权限。用户 (id = 2
) 可能有 access_level = 1
,但此用户有一个覆盖,可撤销对订单的访问权限。这是必须用于确定其权限的行。
问题
我需要加载 table 中所有用户的权限。因此,当我加入用户权限 table 时,我基本上想看看我是否可以加入 users.id = permissions.user
(意味着存在用户特定覆盖),如果不能,我想加入 users.access_level = permissions.id
.我不确定该怎么做。
可能有如下两个查询,但排除了第一个查询中第二个查询的所有结果
1. SELECT email FROM users u JOIN permissions p ON u.id = p.user
2. SELECT email FROM users u JOIN permissions p ON u.access_level = p.id
2022-03-20 更新
hank will also have access_level = 1 meaning the profile is admin. But there is an override for it. The access_level value is not changed in the users table. With that change, your query returns 2 results for hank ; the profile and the override.
如果记录同时具有配置文件和 access_level,您需要首先对结果进行排名(首先通过覆盖)然后 return 仅第一个结果:
WITH cte AS(
SELECT
email
, IF(u.id = p.user
, 'user specific override'
, 'profile'
) AS PermissionType
, ROW_NUMBER() OVER(
PARTITION BY u.id
ORDER BY IF(u.id = p.user, 0, 1)
) AS RowNum
FROM users u
INNER JOIN permissions p ON u.id = p.user OR u.access_level = p.id
)
SELECT *
FROM. cte
WHERE RowNum = 1
结果:
email | PermissionType | RowNum :-------------- | :--------------------- | -----: john@examle.com | profile | 1 hank@examle.com | user specific override | 1
db<>fiddle here
原答案
你试过简单的 OR
SELECT email, IF(u.id = p.user, 'user specific override', 'profile')
FROM users u
INNER JOIN permissions p ON u.id = p.user OR u.access_level = p.id
结果:
email | IF(u.id = p.user, 'user specific override', 'profile') :-------------- | :----------------------------------------------------- john@examle.com | profile hank@examle.com | user specific override
db<>fiddle here