我正在努力编写一个查询来为3个表中的每个id选择具有最高版本号的记录。 worksite id在所有3个表中共享,因此查询worksitedraft.id = 103和worksitesubmission.id = 103将分别返回不同状态的同一工作站。
所有3个表 worksite,worksiteDraft,worksiteSubmission 都有以下列:
id,name,reference,majorrevisionnumber,minorrevisionnumber
基本上我需要将所有三个表合并在一起,然后区分结果,但要确保每个结果都是3个表中具有最高版本号的记录。
到目前为止,我有以下(工作)解决方案,但它非常讨厌,感觉必须有更好的方法。
创建一个联合在一起的3个表中所有工作场所的视图:
CREATE VIEW allworksites AS
SELECT * FROM
(
SELECT id, name, reference, 'worksiteDraft' as type, CONCAT(majorrevisionnumber, '.', minorrevisionnumber) as revisionnumber
FROM worksitedraft
UNION
SELECT id, name, reference, 'worksiteSubmission' as type, CONCAT(majorrevisionnumber, '.', minorrevisionnumber) as revisionnumber
FROM worksitesubmission
UNION
SELECT id, name, reference, 'worksite' as type, CONCAT(majorrevisionnumber, '.', minorrevisionnumber) as revisionnumber
FROM worksite
) as allworksites;
然后使用嵌套选择通过按主要/次要修订号排序并限制为1
来计算类型SELECT * FROM allworksites
WHERE id = 106
AND type =
(
SELECT type FROM
(
SELECT
id,
type,
revisionnumber
FROM
(
SELECT 'worksiteDraft' as type, CONCAT(majorrevisionnumber, '.', minorrevisionnumber) as revisionnumber
FROM worksitedraft
WHERE id = allworksites.id
UNION ALL
SELECT 'worksiteSubmission' as type, CONCAT(majorrevisionnumber, '.', minorrevisionnumber) as revisionnumber
FROM worksitesubmission
WHERE id = allworksites.id
UNION ALL
SELECT 'worksite' as type, CONCAT(majorrevisionnumber, '.', minorrevisionnumber) as revisionnumber
FROM worksite
WHERE id = allworksites.id
) as latestrevision
ORDER BY revisionnumber DESC
limit 1
) as latestrevisiontype
)
是否有另一种(可能是完全不同的)更好的方法来查询这些数据?
编辑。根据要求添加了样本数据和所需结果
| "id"| "name" | "reference"| "majorrevisionnumber" | "minorrevisionnumber"
| 101 | "Worksite One" | "ref-1" | 1 | 0
| 102 | "Worksite Two" | "ref-2" | 1 | 0
| 103 | "Worksite Three"| "ref-3" | 1 | 0
| 104 | "Worksite Four" | "ref-4" | 2 | 0
| 105 | "Worksite Five" | "ref-5" | 2 | 0
| 106 | "Worksite Six" | "ref-6" | 3 | 0
| "id"| "name" | "reference"| "majorrevisionnumber" | "minorrevisionnumber"
| 101 | "Worksite One" | "ref-1" | 1 | 1
| 102 | "Worksite Two" | "ref-2" | 1 | 2
| 103 | "Worksite Three"| "ref-3" | 1 | 2
| 104 | "Worksite Four" | "ref-4" | 1 | 2
| 105 | "Worksite Five" | "ref-5" | 2 | 1
| 106 | "Worksite Six" | "ref-6" | 2 | 2
| "id"| "name" | "reference"| "majorrevisionnumber" | "minorrevisionnumber"
| 101 | "Worksite One" | "ref-1" | 1 | 2
| 102 | "Worksite Two" | "ref-2" | 1 | 3
| 103 | "Worksite Three"| "ref-3" | 1 | 3
| 104 | "Worksite Four" | "ref-4" | 1 | 2
| 105 | "Worksite Five" | "ref-5" | 2 | 2
| 106 | "Worksite Six" | "ref-6" | 2 | 3
| "id"| "name" | "reference"| "majorrevisionnumber" | "minorrevisionnumber"
| 101 | "Worksite One" | "ref-1" | 1 | 2
| 102 | "Worksite Two" | "ref-2" | 1 | 3
| 103 | "Worksite Three"| "ref-3" | 1 | 3
| 104 | "Worksite Four" | "ref-4" | 2 | 0
| 105 | "Worksite Five" | "ref-5" | 2 | 2
| 106 | "Worksite Six" | "ref-6" | 3 | 0
注意:我正在使用postgresql 9.4
编辑: @Gordon_Linoff和@a_horse_with_no_name
的建议后的最终解决方案SELECT DISTINCT ON (id) *
FROM (SELECT id, name, reference, 'worksiteDraft' as type, majorrevisionnumber, minorrevisionnumber
FROM worksitedraft
UNION ALL
SELECT id, name, reference, 'worksiteSubmission' as type, majorrevisionnumber, minorrevisionnumber
FROM worksitesubmission
UNION ALL
SELECT id, name, reference, 'worksite' as type, majorrevisionnumber, minorrevisionnumber
FROM worksite
) allworksites
ORDER BY id, ARRAY[majorrevisionnumber, minorrevisionnumber]::int[] DESC;
答案 0 :(得分:2)
您可以使用单个查询执行此操作。我认为最简单的方法是DISTINCT ON
:
SELECT DISTINCT ON (id) *
FROM (SELECT id, name, reference, 'worksiteDraft' as type,
CONCAT(majorrevisionnumber, '.', minorrevisionnumber) as revisionnumber
FROM worksitedraft
UNION ALL
SELECT id, name, reference, 'worksiteSubmission' as type,
CONCAT(majorrevisionnumber, '.', minorrevisionnumber) as revisionnumber
FROM worksitesubmission
UNION ALL
SELECT id, name, reference, 'worksite' as type,
CONCAT(majorrevisionnumber, '.', minorrevisionnumber) as revisionnumber
FROM worksite
) allworksites
ORDER BY id, revisionnumber DESC;
注意:
UNION ALL
代替UNION
。 UNION
会导致删除重复值的开销,这是不必要的开销。DISTINCT ON
每id
返回一行,第一行根据ORDER BY
子句遇到。编辑:要修复订单号,请不要连接它们:
SELECT DISTINCT ON (id) *
FROM (SELECT id, name, reference, 'worksiteDraft' as type,
majorrevisionnumber, minorrevisionnumber
FROM worksitedraft
UNION ALL
SELECT id, name, reference, 'worksiteSubmission' as type,
majorrevisionnumber, minorrevisionnumber
FROM worksitesubmission
UNION ALL
SELECT id, name, reference, 'worksite' as type,
majorrevisionnumber, minorrevisionnumber
FROM worksite
) allworksites
ORDER BY id, majorrevisionnumber DESC, minorrevisionnumber DESC;