Warm tip: This article is reproduced from serverfault.com, please click

sql-计算用户未联系的组织

(sql - Counting organizations which user has not contacted)

发布于 2020-11-30 16:14:02

我是PostgreSQL的新手。我在架构中创建了以下表:

用户表:

CREATE TABLE public.users
(
    user_id integer NOT NULL DEFAULT nextval('users_user_id_seq'::regclass),
    first_name character varying(90) COLLATE pg_catalog."default" NOT NULL,
    last_name character varying(90) COLLATE pg_catalog."default" NOT NULL,
    email citext COLLATE pg_catalog."default" NOT NULL,
    user_password character varying(90) COLLATE pg_catalog."default" NOT NULL,
    bt_id integer,
    reset_password_token character varying COLLATE pg_catalog."default",
    bstage_id integer,
    CONSTRAINT users_pkey PRIMARY KEY (user_id),
    CONSTRAINT users_email_key UNIQUE (email),
    CONSTRAINT bstage_id FOREIGN KEY (bstage_id)
        REFERENCES public.business_stage (bstage_id) MATCH SIMPLE
        ON UPDATE NO ACTION
        ON DELETE CASCADE,
    CONSTRAINT bt_id FOREIGN KEY (bt_id)
        REFERENCES public.business_type (bt_id) MATCH SIMPLE
        ON UPDATE CASCADE
        ON DELETE CASCADE
        NOT VALID
)
WITH (
    OIDS = FALSE
)

组织表:

CREATE TABLE public.organization
(
    org_id integer NOT NULL DEFAULT nextval('organization_org_id_seq'::regclass),
    name character varying(90) COLLATE pg_catalog."default" NOT NULL,
    description character varying(90) COLLATE pg_catalog."default" NOT NULL,
    email citext COLLATE pg_catalog."default" NOT NULL,
    phone_number character varying(11) COLLATE pg_catalog."default" NOT NULL,
    bt_id integer NOT NULL,
    bs_id integer NOT NULL,
    is_active boolean NOT NULL,
    org_link character varying COLLATE pg_catalog."default",
    CONSTRAINT organization_pkey PRIMARY KEY (org_id),
    CONSTRAINT bs_id FOREIGN KEY (bs_id)
        REFERENCES public.business_step (bs_id) MATCH SIMPLE
        ON UPDATE CASCADE
        ON DELETE CASCADE
        NOT VALID,
    CONSTRAINT bt_id FOREIGN KEY (bt_id)
        REFERENCES public.business_type (bt_id) MATCH SIMPLE
        ON UPDATE CASCADE
        ON DELETE CASCADE
        NOT VALID
)
WITH (
    OIDS = FALSE
)

最后是Organization_rating表:

CREATE TABLE public.organization_rating
(
    rating integer NOT NULL,
    user_id integer NOT NULL,
    organization_id integer NOT NULL,
    rating_comment character varying(255) COLLATE pg_catalog."default",
    CONSTRAINT organization_rating_pkey PRIMARY KEY (user_id, organization_id),
    CONSTRAINT user_id FOREIGN KEY (user_id)
        REFERENCES public.users (user_id) MATCH SIMPLE
        ON UPDATE CASCADE
        ON DELETE CASCADE,
    CONSTRAINT stars CHECK (rating >= 1 AND rating < 5)
)
WITH (
    OIDS = FALSE
)

使用此架构,组织可以拥有一种业务类型,在该业务类型中,也向具有该业务类型的用户提供支持。提供此支持后,用户可以使用organization_rating对该组织进行评分。遵循此逻辑,我想执行一个查询,该查询提供了用户已联系的组织所评级的百分比与用户仍需要对其进行评级的组织的百分比。例如,假设user_id 1为组织1评级,该组织与用户具有相同的业务类型。另外9个组织具有相同的业务类型,但用户尚未对这些组织进行评分。该查询将返回10%。

我有以下查询来统计用户已联系的组织:

Select U.first_name, COUNT(R.rating)
From users as U INNER JOIN organization_rating as R on U.user_id = R.user_id
Inner join organization as O on O.org_id = R.organization_id
Where O.bt_id = 1 AND R.user_id != 62
Group by U.first_name;

我如何计算该用户尚未联系的组织以及联系的百分比与仍要联系的百分比?

如果你还可以将我引至一些站点,这些站点可以帮助我学习更多PostgreSQL和不同的功能,我将不胜感激。先感谢你!

Questioner
Noname
Viewed
12
GMB 2020-12-01 02:03:43

你可以cross join使用和组织获取所有可能的组合,然后在桥表中添加left join最后一步是条件聚合:

SELECT u.first_name, 
    COUNT(*) FILTER (WHERE r.user_id IS NULL) as cnt_not_contacted,
    AVG((r.user_id IS NOT NULL)::int) as avg_contacted
FROM users u
CROSS JOIN organization o
LEFT JOIN organization_rating r ON u.user_id = r.user_id AND o.org_id = r.organization_id
WHERE o.bt_id = 1 AND u.user_id <> 62
GROUP BY u.user_id