【问题标题】:PostgreSQL ARRAY_AGG return separate arraysPostgreSQL ARRAY_AGG 返回单独的数组
【发布时间】:2021-11-26 19:22:03
【问题描述】:

用例是这样的:每个用户都可以创建自己的游戏,并跟踪他们在哪个国家/地区玩过游戏。

我想创建一个查询,我可以在其中获取该用户的所有游戏列表以及该游戏在哪个国家/地区玩。我只对国家/地区 ID 感兴趣。

我有 4 个表:users、games、country 和一个 games_countries_xref 表。

CREATE SEQUENCE countries_id_seq INCREMENT 1 MINVALUE 1 MAXVALUE 2147483647 START 1 CACHE 1;

CREATE TABLE "public"."countries" (
    "id" integer DEFAULT nextval('countries_id_seq') NOT NULL,
    "name" character varying(200) NOT NULL,
    CONSTRAINT "countries_pkey" PRIMARY KEY ("id")
) WITH (oids = false);


INSERT INTO "countries" ("id", "name") VALUES
(1, 'USA'),
(2, 'Japan'),
(3, 'Australia');

CREATE SEQUENCE games_id_seq INCREMENT 1 MINVALUE 1 MAXVALUE 2147483647 START 3 CACHE 1;

CREATE TABLE "public"."games" (
    "id" integer DEFAULT nextval('games_id_seq') NOT NULL,
    "user_id" integer NOT NULL,
    "name" character varying(200) NOT NULL,
    CONSTRAINT "games_pkey" PRIMARY KEY ("id")
) WITH (oids = false);

INSERT INTO "games" ("id", "user_id", "name") VALUES
(1, 1,  'Monopoly'),
(2, 1,  'Zelda'),
(3, 2,  'Hide & Seek');

CREATE TABLE "public"."games_countries_xref" (
    "game_id" integer NOT NULL,
    "country_id" integer NOT NULL
) WITH (oids = false);

INSERT INTO "games_countries_xref" ("game_id", "country_id") VALUES
(1, 1),
(1, 2),
(1, 3),
(2, 2),
(3, 1);

CREATE SEQUENCE users_id_seq INCREMENT 1 MINVALUE 1 MAXVALUE 2147483647 START 2 CACHE 1;

CREATE TABLE "public"."users" (
    "id" integer DEFAULT nextval('users_id_seq') NOT NULL,
    "name" character varying(200) NOT NULL,
    CONSTRAINT "users_pkey" PRIMARY KEY ("id")
) WITH (oids = false);

INSERT INTO "users" ("id", "name") VALUES
(1, 'Jack'),
(2, 'Jason');

查询数据时,我尝试使用ARRAY_AGG:

WITH country_ids AS (
    SELECT g.user_id, ARRAY_AGG(gcx.country_id) AS country_ids
    FROM games AS g
    LEFT JOIN games_countries_xref AS gcx ON g.id = gcx.game_id
    GROUP BY g.user_id
)
SELECT g.name, country_ids
FROM games AS g
    NATURAL LEFT JOIN country_ids
WHERE g.user_id = 1

但这给了我这个输出:

name     | country_ids
------------------
Monopoly | {1,2,3,2}
Zelda    | {1,2,3,2}

当我在寻找这个时:

name     | country_ids
------------------
Monopoly | {1,2,3}
Zelda    | {2}

我知道我可能在子查询中做错了什么,但我不知道是什么。 有什么想法吗?

【问题讨论】:

    标签: arrays postgresql


    【解决方案1】:

    您与ARRAY_AGG 走在正确的轨道上,但在加入时有点过于激进。您只需要在 3 个表上进行简单的连接(1 个左,1 个内)

        select g.name,array_agg(gcx.country_id) as country_ids  
          from games g 
          join users u on u.id = g.user_id
          left join games_countries_xref gcx on gcx.game_id = g.id
         where u.id = 1
         group by g.name;
     
    +----------+-------------+
    |   name   | country_ids |
    +----------+-------------+
    | Monopoly | {1,2,3}     |
    | Zelda    | {2}         |
    +----------+-------------+
    

    【讨论】:

    • 有时它可以如此简单:) 非常感谢!!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-26
    • 2018-04-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-08
    • 2017-08-23
    • 1970-01-01
    相关资源
    最近更新 更多