【问题标题】:Query database for distinct values and aggregate data based on condition查询数据库以获取不同的值并根据条件聚合数据
【发布时间】:2020-02-05 00:42:08
【问题描述】:

我正在尝试从 Postgres 数据库中提取不同的项目,根据条件将表中的列与另一个表中的列配对。简化版如下所示:

CREATE TABLE users
(
  id SERIAL PRIMARY KEY,
  name VARCHAR(255)
);

CREATE TABLE photos
(
  id INT PRIMARY KEY,
  user_id INTEGER REFERENCES users(id),
  flag VARCHAR(255)
);

INSERT INTO users VALUES (1, 'Bob');
INSERT INTO users VALUES (2, 'Alice');
INSERT INTO users VALUES (3, 'John');

INSERT INTO photos VALUES (1001, 1, 'a');
INSERT INTO photos VALUES (1002, 1, 'b');
INSERT INTO photos VALUES (1003, 1, 'c');
INSERT INTO photos VALUES (1004, 2, 'a');
INSERT INTO photos VALUES (1004, 2, 'x');

我需要的是提取每个用户名,只提取一次,并为每个用户提取一个标志值。标志值应该优先考虑一个特定的值,比如说b。所以,结果应该是这样的:

Bob    b 
Alice  a

Bob 拥有一张带有b 标志的照片,而Alice 没有,John 没有照片。对于Alice,标志值的输出并不重要(ax 一样好)只要她没有标记为b 的照片。

我发现最接近的是一些自联接查询,其中标志值将使用min()max() 聚合,但我正在寻找一个特定的值,它不是第一个,也不是最后一个。此外,我发现您可以定义自己的聚合函数,但我想知道是否有更简单的方法来调节查询以获得所需的数据。

谢谢!

【问题讨论】:

    标签: sql postgresql distinct-values


    【解决方案1】:

    这是一个聚合方法:

    select u.name,
           coalesce(max(flag) filter (where flag = 'b'),
                    min(flag)
                   ) as flag
    from users u left join
         photos p
         on u.id = p.user_id
    group by u.id, u.name;
    

    也就是说,更典型的方法是优先级查询。也许:

    select distinct on (u.id) u.name, p.flag
    from users u left join
         photos p
         on u.id = p.user_id
    order by u.id, (p.flag = 'b') desc;
    

    【讨论】:

    • 谢谢您,先生!我刚刚学到了两个关于 SQL 的新东西。
    猜你喜欢
    • 2023-01-08
    • 1970-01-01
    • 2020-01-14
    • 2021-12-01
    • 2019-02-11
    • 1970-01-01
    • 2017-08-29
    • 2022-11-26
    • 1970-01-01
    相关资源
    最近更新 更多