Mysql left join with double same-table 关系 where 子句
Mysql left join with double same-table relation where clause
基本上我有这 2 个简单的 mysql 表:
CREATE TABLE `users` (
`id` int(10) UNSIGNED NOT NULL,
`name` varchar(255) NOT NULL,
`relation` int(10) UNSIGNED DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `mytable` (
`id` int(10) UNSIGNED NOT NULL,
`user` int(10) UNSIGNED NOT NULL,
`data` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`tier` tinyint(3) UNSIGNED NOT NULL,
`parent_id` int(10) UNSIGNED DEFAULT NULL COMMENT 'same table'
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `users` (`id`, `name`, `relation`) VALUES
(12, 'user1', 5),
(20, 'user2', NULL),
(21, 'user3', NULL);
INSERT INTO `mytable` (`id`, `user`, `data`, `tier`, `parent_id`) VALUES
(1, 12, 'test1', 1, NULL),
(2, 20, 'test2', 2, 1),
(3, 21, 'test3', 3, 1),
(4, 20, 'test4', 1, NULL);
我需要 select 'mytable' 中与 users.relation = 5
相关的所有行
为此,我使用以下查询:
SELECT mytable.*
FROM mytable
LEFT JOIN users ON mytable.user = users.id
WHERE users.relation = 5
问题是我还需要 select mytable
中具有 parent_id 的行与上述结果相关联。
WHERE mytable.id = X OR mytable.parent_id = X
基本上在这个例子中,预期的输出应该是 mytable 除了最后一行之外的所有行
(因为没有连接users.relation = 5)
您需要 mytable
的另一个连接到您的查询:
SELECT m.*
FROM mytable m INNER JOIN (
SELECT m.*
FROM mytable m
INNER JOIN users u ON m.user = u.id
WHERE u.relation = 5
) t ON t.id IN (m.id, m.parent_id)
我将联接更改为 INNER
联接,因为尽管您使用 LEFT
联接,但 WHERE
子句将其更改为 INNER
,因为它会过滤掉任何不匹配的行。
参见demo。
结果:
> id | user | data | tier | parent_id
> -: | ---: | :---- | ---: | --------:
> 1 | 12 | test1 | 1 | null
> 2 | 20 | test2 | 2 | 1
> 3 | 21 | test3 | 3 | 1
基本上我有这 2 个简单的 mysql 表:
CREATE TABLE `users` (
`id` int(10) UNSIGNED NOT NULL,
`name` varchar(255) NOT NULL,
`relation` int(10) UNSIGNED DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `mytable` (
`id` int(10) UNSIGNED NOT NULL,
`user` int(10) UNSIGNED NOT NULL,
`data` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`tier` tinyint(3) UNSIGNED NOT NULL,
`parent_id` int(10) UNSIGNED DEFAULT NULL COMMENT 'same table'
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `users` (`id`, `name`, `relation`) VALUES
(12, 'user1', 5),
(20, 'user2', NULL),
(21, 'user3', NULL);
INSERT INTO `mytable` (`id`, `user`, `data`, `tier`, `parent_id`) VALUES
(1, 12, 'test1', 1, NULL),
(2, 20, 'test2', 2, 1),
(3, 21, 'test3', 3, 1),
(4, 20, 'test4', 1, NULL);
我需要 select 'mytable' 中与 users.relation = 5
相关的所有行为此,我使用以下查询:
SELECT mytable.*
FROM mytable
LEFT JOIN users ON mytable.user = users.id
WHERE users.relation = 5
问题是我还需要 select mytable
中具有 parent_id 的行与上述结果相关联。
WHERE mytable.id = X OR mytable.parent_id = X
基本上在这个例子中,预期的输出应该是 mytable 除了最后一行之外的所有行 (因为没有连接users.relation = 5)
您需要 mytable
的另一个连接到您的查询:
SELECT m.*
FROM mytable m INNER JOIN (
SELECT m.*
FROM mytable m
INNER JOIN users u ON m.user = u.id
WHERE u.relation = 5
) t ON t.id IN (m.id, m.parent_id)
我将联接更改为 INNER
联接,因为尽管您使用 LEFT
联接,但 WHERE
子句将其更改为 INNER
,因为它会过滤掉任何不匹配的行。
参见demo。
结果:
> id | user | data | tier | parent_id
> -: | ---: | :---- | ---: | --------:
> 1 | 12 | test1 | 1 | null
> 2 | 20 | test2 | 2 | 1
> 3 | 21 | test3 | 3 | 1