为什么我不能针对递归视图发出与支持它的 table 相同的查询?
Why can I not issue the same query against a recursive view as I can on the table backing it?
我有一个 tags
table,我在上面定义了一个来自递归 CTE 的视图,包含标签 table:
的所有列
CREATE VIEW tags_paths AS
WITH RECURSIVE tag_path (id, created_at, updated_at, community_id, tag_set_id, wiki_markdown,
wiki, excerpt, parent_id, name, path) AS
(
SELECT id, created_at, updated_at, community_id, tag_set_id, wiki_markdown,
wiki, excerpt, parent_id, name, name as path
FROM tags
WHERE parent_id IS NULL
UNION ALL
SELECT t.id, t.created_at, t.updated_at, t.community_id, t.tag_set_id,
t.wiki_markdown, t.wiki, t.excerpt, t.parent_id, t.name,
concat(tp.name, ' > ', t.name) as path
FROM tag_path AS tp JOIN tags AS t ON tp.id = t.parent_id
)
SELECT * FROM tag_path
ORDER BY path;
我可以针对 tags
table 发出此查询就好了:
SELECT tags.*, COUNT(posts.id) AS post_count
FROM `tags`
LEFT OUTER JOIN `posts_tags` ON `posts_tags`.`tag_id` = `tags`.`id`
LEFT OUTER JOIN `posts` ON `posts`.`community_id` = 2 AND `posts`.`id` = `posts_tags`.`post_id`
WHERE `tags`.`community_id` = 2 AND `tags`.`tag_set_id` = 3
GROUP BY tags.id ORDER BY COUNT(posts.id) DESC LIMIT 96 OFFSET 0;
但是,针对 tags_paths
视图发出的等效查询:
SELECT tags_paths.*, COUNT(posts.id) AS post_count
FROM `tags_paths`
LEFT OUTER JOIN `posts_tags` ON `posts_tags`.`tag_id` = `tags_paths`.`id`
LEFT OUTER JOIN `posts` ON `posts`.`community_id` = 2 AND `posts`.`id` = `posts_tags`.`post_id`
WHERE `tags_paths`.`community_id` = 2 AND `tags_paths`.`tag_set_id` = 3
GROUP BY tags_paths.id ORDER BY COUNT(posts.id) DESC LIMIT 96 OFFSET 0;
返回错误,特别是:
[42000][1055] Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column
'tags_paths.created_at' which is not functionally dependent on columns in GROUP BY clause; this is
incompatible with sql_mode=only_full_group_by
为什么?我该怎么办?
正如@Akina 所述,id
是 table tags
上的键,但不是视图上的键。因此,根据 SQL 标准的规定,无法在视图中针对 id
列的其余列建立直接依赖关系。
你有两个选择。您可以:
将所有列添加到 GROUP BY
子句。有时这对于大型类型(例如 TEXT
或二进制文件)是不可能的。
或者,您可以聚合 SELECT
子句中的列。
下面是使用后者修改后的 SQL 语句:
SELECT
tags_paths.id,
max(tags_paths.created_at) as created_at,
max(tags_paths.updated_at) as updated_at,
max(tags_paths.community_id) as community_id,
max(tags_paths.tag_set_id) as tag_set_id,
max(tags_paths.wiki_markdown) as markdown,
max(tags_paths.wiki) as wiki,
max(tags_paths.excerpt) as excerpt,
max(tags_paths.parent_id) as parent_id,
max(tags_paths.name) as name,
max(tags_paths.path) as path,
COUNT(posts.id) AS post_count
FROM `tags_paths`
LEFT OUTER JOIN `posts_tags` ON `posts_tags`.`tag_id` = `tags_paths`.`id`
LEFT OUTER JOIN `posts` ON `posts`.`community_id` = 2
AND `posts`.`id` = `posts_tags`.`post_id`
WHERE `tags_paths`.`community_id` = 2 AND `tags_paths`.`tag_set_id` = 3
GROUP BY tags_paths.id
ORDER BY COUNT(posts.id) DESC
LIMIT 96
OFFSET 0;
是的,变长了。
我有一个 tags
table,我在上面定义了一个来自递归 CTE 的视图,包含标签 table:
CREATE VIEW tags_paths AS
WITH RECURSIVE tag_path (id, created_at, updated_at, community_id, tag_set_id, wiki_markdown,
wiki, excerpt, parent_id, name, path) AS
(
SELECT id, created_at, updated_at, community_id, tag_set_id, wiki_markdown,
wiki, excerpt, parent_id, name, name as path
FROM tags
WHERE parent_id IS NULL
UNION ALL
SELECT t.id, t.created_at, t.updated_at, t.community_id, t.tag_set_id,
t.wiki_markdown, t.wiki, t.excerpt, t.parent_id, t.name,
concat(tp.name, ' > ', t.name) as path
FROM tag_path AS tp JOIN tags AS t ON tp.id = t.parent_id
)
SELECT * FROM tag_path
ORDER BY path;
我可以针对 tags
table 发出此查询就好了:
SELECT tags.*, COUNT(posts.id) AS post_count
FROM `tags`
LEFT OUTER JOIN `posts_tags` ON `posts_tags`.`tag_id` = `tags`.`id`
LEFT OUTER JOIN `posts` ON `posts`.`community_id` = 2 AND `posts`.`id` = `posts_tags`.`post_id`
WHERE `tags`.`community_id` = 2 AND `tags`.`tag_set_id` = 3
GROUP BY tags.id ORDER BY COUNT(posts.id) DESC LIMIT 96 OFFSET 0;
但是,针对 tags_paths
视图发出的等效查询:
SELECT tags_paths.*, COUNT(posts.id) AS post_count
FROM `tags_paths`
LEFT OUTER JOIN `posts_tags` ON `posts_tags`.`tag_id` = `tags_paths`.`id`
LEFT OUTER JOIN `posts` ON `posts`.`community_id` = 2 AND `posts`.`id` = `posts_tags`.`post_id`
WHERE `tags_paths`.`community_id` = 2 AND `tags_paths`.`tag_set_id` = 3
GROUP BY tags_paths.id ORDER BY COUNT(posts.id) DESC LIMIT 96 OFFSET 0;
返回错误,特别是:
[42000][1055] Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column
'tags_paths.created_at' which is not functionally dependent on columns in GROUP BY clause; this is
incompatible with sql_mode=only_full_group_by
为什么?我该怎么办?
正如@Akina 所述,id
是 table tags
上的键,但不是视图上的键。因此,根据 SQL 标准的规定,无法在视图中针对 id
列的其余列建立直接依赖关系。
你有两个选择。您可以:
将所有列添加到
GROUP BY
子句。有时这对于大型类型(例如TEXT
或二进制文件)是不可能的。或者,您可以聚合
SELECT
子句中的列。
下面是使用后者修改后的 SQL 语句:
SELECT
tags_paths.id,
max(tags_paths.created_at) as created_at,
max(tags_paths.updated_at) as updated_at,
max(tags_paths.community_id) as community_id,
max(tags_paths.tag_set_id) as tag_set_id,
max(tags_paths.wiki_markdown) as markdown,
max(tags_paths.wiki) as wiki,
max(tags_paths.excerpt) as excerpt,
max(tags_paths.parent_id) as parent_id,
max(tags_paths.name) as name,
max(tags_paths.path) as path,
COUNT(posts.id) AS post_count
FROM `tags_paths`
LEFT OUTER JOIN `posts_tags` ON `posts_tags`.`tag_id` = `tags_paths`.`id`
LEFT OUTER JOIN `posts` ON `posts`.`community_id` = 2
AND `posts`.`id` = `posts_tags`.`post_id`
WHERE `tags_paths`.`community_id` = 2 AND `tags_paths`.`tag_set_id` = 3
GROUP BY tags_paths.id
ORDER BY COUNT(posts.id) DESC
LIMIT 96
OFFSET 0;
是的,变长了。