SQL 视图,其计数取决于当前用户

SQL view with count depending on current user

提问人:brcebn 提问时间:11/14/2023 最后编辑:brcebn 更新时间:11/14/2023 访问量:90

问:

目的:

  1. 列出所有唯一身份事件
  2. 有一个基于当前用户调用的专用列reviewed
  3. 如果未邀请当前用户,则必须列出事件

可能的情况:

  1. 用户被邀请
  2. 未邀请用户

每个“已确认”用户都会审核活动(并非所有邀请都已确认) “审查”条件:

  • 存在审查
  • 至少有一个附件链接到本综述

我在 Postgresql 14.7 中有 4 个表。

  • 事件
  • 邀请(1-1/用户/事件)
  • 评论 (0-1/邀请)
  • 附件 (0-N/review)

他们来了:

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;)

我已经阅读了 Select first row in each GROUP BY group? 几十遍了,但我不确定它是否适合我的情况

在我看来,这种观点是“暂时的”,直到我使用当前的用户邀请来限定结果的范围。

我有一部分解决方案使用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 JOINmanual_invitation_idWHERE rn=1rn

我什至不知道在单个查询中是否可能。我想避免子查询,因为它是应用程序中最常用的查询之一。此外,它位于 Rails 应用程序中,因此我不确定使用 ActiveRecord 可以轻松处理子查询。

SQL Ruby-on-Rails PostgreSQL SQL视图

评论

0赞 zaphodbln_ 11/14/2023
我认为第一个查询非常接近预期的输出。也许您应该在 select 和 group 语句中添加一个invitation.user_id - 然后您可以查询视图中的“当前用户”。Rails-App 中的另一种方法是 through-statement: guides.rubyonrails.org/...——这样你就可以得到邀请函和附件,如果存在的话,可以进行检查。
0赞 Erwin Brandstetter 11/14/2023
评论被视为与邀请有关,而不是与活动有关。为什么?人们会期望“审查”与活动有关,而不是邀请。更一般地说,根据全貌给出答案要容易得多。表定义,Postgres 版本。理想情况下,摆弄一些测试数据。
0赞 brcebn 11/14/2023
@ErwinBrandstetter实际上,每个用户(完全受邀)都需要为活动添加评论。因此,一个活动有很多评论,因为它有完全确认的邀请。
0赞 Erwin Brandstetter 11/14/2023
请澄清查询的目的。是否要列出所有现有的偶数/邀请/评论组合。LEFT JOIN 表示同样多。准确无误的目标 - 在问题中,而不仅仅是评论
0赞 brcebn 11/14/2023
我想要带有列的事件列表作为布尔值。reviewed

答:

1赞 Erwin Brandstetter 11/14/2023 #1

列出所有事件,并带有当前用户的标志:reviewed

SELECT 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;

EXISTS 子查询表达式可能是最快的。

如果您想要当前用户的结果,请不要为此使用泛型。使用给定的查询,或将其包装到返回集合的 FUNCTION 中。例:VIEW

评论

0赞 brcebn 11/14/2023
我想避免子查询。另外,在这里,我将限定当前用户被邀请的所有事件,但我想要所有这些事件。我在描述中添加了很多细节。这还不够清楚。🙂
0赞 Erwin Brandstetter 11/14/2023
没有理由避免.“subquery”只是另一个返回 .EXISTSboolean
0赞 brcebn 11/14/2023
我害怕子查询的性能问题(我肯定错了)。是否有可能在视图中拥有它并且仍然具有动态性?$current_user_id
0赞 Erwin Brandstetter 11/14/2023
我给出这个查询是因为我希望它是最快的。如果您希望为当前用户自定义结果,则一开始就使用 A 是错误的工具。VIEW
1赞 Erwin Brandstetter 11/15/2023
优秀的手册。以及 SO 和 dba.SE 上值得信赖的用户的回答。性能优化是棘手的,需要知识、经验和科学思维。一路顺风!:)