我公司中有几个组织已将分配给它们的“组类别”与个人优先级相关联。我有疑问
... WHERE gc.priority_level = (SELECT MIN(gc_inner.priority_level) ...), as first_category
和
... WHERE gc.priority_level = (SELECT MAX(gc_inner.priority_level) ...), as third_category
gc 优先级可以根据组织的不同而变化,有些只有 1 个优先级,而另一些则最多为 3 个,因此我需要能够找到位于最低优先级和最高优先级之间的潜在 secondary_category。
(
SELECT g.name
FROM groups g
INNER JOIN group_categories gc ON gc.id = g.group_category_id INNER JOIN item_groups ig ON ig.group_id = g.id AND ig.item_id = i1."id" WHERE gc.priority_level = (
SELECT MIN(gc_inner.priority_level)
FROM group_categories gc_inner
INNER JOIN item_groups ig_inner ON ig_inner.group_id = g.id
AND ig_inner.item_id = i1."id"
WHERE gc_inner.id = g.group_category_id AND gc_inner.type = 'item' )
AND gc.type = 'item'
LIMIT 1
) AS "primary_item_category",
(
SELECT g.name
FROM groups g
INNER JOIN group_categories gc ON gc.id = g.group_category_id
INNER JOIN item_groups ig ON ig.group_id = g.id
AND ig.item_id = i1."id"
WHERE gc.priority_level = (
SELECT MIN(gc_inner.priority_level)
FROM group_categories gc_inner
INNER JOIN item_groups ig_inner ON ig_inner.group_id = g.id
AND ig_inner.item_id = i1."id"
AND gc_inner.priority_level > (
SELECT MIN(gc_inner2.priority_level)
FROM group_categories gc_inner2
INNER JOIN item_groups ig_inner2 ON ig_inner2.group_id = g.id
AND ig_inner2.item_id = i1."id" )
)
AND gc.type = 'item'
LIMIT 1
) AS "second_item_category",
(
SELECT g.name
FROM groups g
INNER JOIN group_categories gc ON gc.id = g.group_category_id
INNER JOIN item_groups ig ON ig.group_id = g.id
AND ig.item_id = i1."id"
WHERE gc.priority_level = (
SELECT MAX(gc_inner.priority_level)
FROM group_categories gc_inner
INNER JOIN item_groups ig_inner ON ig_inner.group_id = g.id
AND ig_inner.item_id = i1."id")
AND gc.type = 'item'
LIMIT 1
) AS "third_item_category",
...
我在测试中设置了这个:`org = insert(:organization)
group_category1 = insert(:group_category, type: "organization", priority_level: 1, organization: org, name: "OrganizationCategory") group_category2 = insert(:group_category, type: "item", priority_level: 2, organization: org, name: "PrimaryItemCategory") group_category3 = insert(:group_category, type: "item", priority_level: 3, organization: org, name: "SecondItemCategory") group_category4 = insert(:group_category, type: "item", priority_level: 4, organization: org, name: "ThirdItemCategory") org_group1 = Factory.insert(:group, group_category: group_category1, name: "org_group1") org_group2 = Factory.insert(:group, group_category: group_category2, name: "org_group2") org_group3 = Factory.insert(:group, group_category: group_category3, name: "org_group3") org_group4 = Factory.insert(:group, group_category: group_category4, name: "org_group4")
所以我期待“org_group3”的返回,但在拉取 secondary_item_category 时却得到 nil,但所有其他类别都正确返回。
如果我将 secondary_item_category 更改为
( SELECT g.name FROM groups g INNER JOIN group_categories gc ON gc.id = g.group_category_id INNER JOIN item_groups ig ON ig.group_id = g.id AND ig.item_id = i1."id" WHERE gc.priority_level = ( SELECT priority_level FROM ( SELECT gc_inner.priority_level, ROW_NUMBER() OVER (ORDER BY gc_inner.priority_level) AS rn, COUNT(*) OVER () AS cnt FROM group_categories gc_inner INNER JOIN item_groups ig_inner ON ig_inner.group_id = g.id AND ig_inner.item_id = i1."id" WHERE gc_inner.id = g.group_category_id AND gc_inner.type = 'item' ) subquery WHERE rn = (cnt + 1) / 2 ) AND gc.type = 'item' LIMIT 1 ) AS "second_item_category",
然后返回 org_group2 而不是 org_group3。
“项目”类型存在一个、两个或三个组类别。您想按priority_level 对它们进行排序。对于每个组类别,您要选择其中一个组名称,并根据其优先级排名将其称为first_category、second_category 和third_category。
您可以使用窗口函数来做到这一点
DENSE_RANK
:
WITH
ranked AS
(
SELECT
g.name,
DENSE_RANK() OVER (ORDER BY gc.priority_level) AS rn
FROM groups g
INNER JOIN group_categories gc ON gc.id = g.group_category_id
WHERE gc.type = 'item'
)
SELECT
ANY_VALUE(name) FILTER (WHERE rn = 1) AS first_category,
ANY_VALUE(name) FILTER (WHERE rn = 2) AS second_category,
ANY_VALUE(name) FILTER (WHERE rn = 3) AS third_category
FROM ranked;
这是针对多个类别类型的相同查询:
WITH
ranked AS
(
SELECT
gc.type,
g.name,
DENSE_RANK() OVER (PARTITION BY gc.type ORDER BY gc.priority_level) AS rn
FROM groups g
INNER JOIN group_categories gc ON gc.id = g.group_category_id
)
SELECT
type,
ANY_VALUE(name) FILTER (WHERE rn = 1) AS first_category,
ANY_VALUE(name) FILTER (WHERE rn = 2) AS second_category,
ANY_VALUE(name) FILTER (WHERE rn = 3) AS third_category
FROM ranked
GROUP BY type
ORDER BY type;