GROUP BY 和 DISTINCT ON 对表和视图的工作方式不同

GROUP BY and DISTINCT ON working differently for tables and views

我有一个 table Design 和一个名为 ArchivedDesign 的 table 观点。视图声明为:

CREATE OR REPLACE VIEW public."ArchivedDesign" ("RootId",  "Id", "Created", "CreatedBy", "Modified", "ModifiedBy", "VersionStatusId", "OrganizationId")
AS
SELECT DISTINCT ON (des."RootId") "RootId", des."Id", des."Created", des."CreatedBy", des."Modified", des."ModifiedBy", des."VersionStatusId", des."OrganizationId"
FROM public."Design" AS des
JOIN public."VersionStatus" AS vt ON des."VersionStatusId" = vt."Id"
WHERE vt."Code" = 'Archived'
ORDER BY "RootId", des."Modified" DESC;

然后,我有一个大型查询,它获取最新更改、缩略图等的简短摘要。整个查询并不重要,但它包含两个几乎相同的子查询 - 一个用于主要 table 和和一个视图。

SELECT DISTINCT ON (1) x."Id",
                TRIM(con."Name") AS "Contributor",
                extract(epoch from x."Modified") * 1000 AS "Modified",
                x."VersionStatusId",
                x."OrganizationId"
FROM public."Design" AS x
JOIN "Contributor" AS con ON con."DesignId" = x."Id"
WHERE x."OrganizationId" = ANY (ARRAY[]::uuid[])
AND x."VersionStatusId" = ANY (ARRAY[]::uuid[])
GROUP BY x."Id", con."Name"
ORDER BY x."Id";

SELECT DISTINCT ON (1) x."Id",
                TRIM(con."Name") AS "Contributor",
                extract(epoch from x."Modified") * 1000 AS "Modified",
                x."VersionStatusId",
                x."OrganizationId"
FROM public."ArchivedDesign" AS x
JOIN "Contributor" AS con ON con."DesignId" = x."Id"
WHERE x."OrganizationId" = ANY (ARRAY[]::uuid[])
AND x."VersionStatusId" = ANY (ARRAY[]::uuid[])
GROUP BY x."Id", con."Name"
ORDER BY x."Id";

Link 到 SQL fiddle: http://sqlfiddle.com/#!17/d1d0f/1

查询对 table 有效,但对视图失败并出现错误 column x."Modified" must appear in the GROUP BY clause or be used in an aggregate function。我不明白为什么这两个查询的行为会有所不同?如何修复视图查询使其与 table 查询的工作方式相同?

我的最终目标是用视图子查询替换所有 table 子查询,这样我们就可以轻松分离草稿、活动和存档设计。

你得到那个错误是因为当你直接查询 table 时,Postgres 能够识别 table 的主键并且知道按它分组就足够了。

Quote from the manual

When GROUP BY is present, or any aggregate functions are present, it is not valid for the SELECT list expressions to refer to ungrouped columns except within aggregate functions or when the ungrouped column is functionally dependent on the grouped columns, since there would otherwise be more than one possible value to return for an ungrouped column. A functional dependency exists if the grouped columns (or a subset thereof) are the primary key of the table containing the ungrouped column

(强调我的)

查询视图时,Postgres 无法检测到在直接查询 table 时可能有 "shortened" GROUP BY 的功能依赖性。