目标:
reviewed
的专用列可能的情况:
活动由每个“已确认”用户审核(并非所有邀请均已确认) 需“审核”的条件:
我有4张桌子。
他们在这里:
CREATE TABLE public.events (
id bigint NOT NULL,
name character varying NOT NULL,
start_at timestamp without time zone NOT NULL,
end_at timestamp without time zone NOT NULL
);
CREATE TABLE public.invitations (
id bigint NOT NULL,
status integer DEFAULT 0 NOT NULL,
user_id bigint NOT NULL,
event_id bigint NOT NULL,
);
CREATE TABLE public.reviews (
id bigint NOT NULL,
reviewable_id bigint NOT NULL,
reviewable_type character varying NOT NULL,
comment text
);
CREATE TABLE public.attachments (
id bigint NOT NULL,
attachable_id bigint NOT NULL,
attachable_type character varying NOT NULL
);
我得到了一个 SQL 视图,但它是错误的,因为
reviewed
与当前用户邀请不匹配(它是随机的,基于邀请创建)。
这是我当前的代码
CREATE OR REPLACE VIEW my_view AS
SELECT
((e.enable_review = true AND r.id IS NOT NULL AND count(a) > 0 ) OR e.enable_review = false) AS reviewed,
e.*
FROM events e
LEFT JOIN invitations i ON i.event_id = e.id
LEFT JOIN reviews r ON (r.reviewable_type = 'Invitation' AND r.reviewable_id = i.id)
LEFT JOIN attachments a ON (a.attachable_type = 'Review' AND a.attachable_id = r.id)
GROUP BY e.id, r.id;)
我已经阅读了选择每个 GROUP BY 组中的第一行?数十次,但我不确定它是否适合我的情况
在我看来,这个视图是“临时的”,直到我用当前用户邀请来确定结果范围。
我有部分解决方案使用
row_number
CREATE OR REPLACE VIEW my_view AS
SELECT
((e.enable_review = true AND r.id IS NOT NULL AND count(a) > 0 ) OR e.enable_review = false) AS reviewed,
e.*,
row_number() OVER (PARTITION BY i.event_id ORDER BY i.id DESC) AS rn,
i.id as manual_invitation_id
FROM events e
LEFT JOIN invitations i ON i.event_id = e.id
LEFT JOIN reviews r ON (r.reviewable_type = 'Invitation' AND r.reviewable_id = i.id)
LEFT JOIN attachments a ON (a.attachable_type = 'Review' AND a.attachable_id = r.id)
GROUP BY e.id, i.id, r.id;)
然后,当我想要确定当前用户的范围时,我会在
LEFT OUTER JOIN
上使用 manual_invitation_id
,并将其与 WHERE rn=1
组合起来。
但rn
可以是任何数字,而不仅仅是一个。所以范围不起作用。
我什至不知道是否可以在单个查询中实现。我想避免子查询,因为它是应用程序中最常用的查询之一。此外,它位于 Rails 应用程序内部,因此我不确定是否可以使用 ActiveRecord 轻松处理子查询。
要列出所有事件,
EXISTS
子查询可能是最好的。
仍然不清楚当前用户是如何进入这个状态的。这是我的猜测:
SELECT e.enable_review
, EXISTS (
SELECT
FROM invitations i
JOIN reviews r ON r.reviewable_id = i.id
JOIN attachments a ON a.attachable_id = r.id
WHERE i.user_id = $current_user_id -- ???
AND i.event_id = e.id
AND r.reviewable_type = 'Invitation'
AND a.attachable_type = 'Review'
) AS reviewed
, e.*
FROM events e;