SQL(Postgres)为列表参数中的每个项目获取一行,其优先顺序由另一列指定

Posted

技术标签:

【中文标题】SQL(Postgres)为列表参数中的每个项目获取一行,其优先顺序由另一列指定【英文标题】:SQL (Postgres) getting one row for each item in a list parameter with an order of preference specified by another column 【发布时间】:2019-04-04 16:59:15 【问题描述】:

(使用最近的 postgres)

考虑表contact_methods

id | person | contact_type | other_data
1  | 1      | ""           | stuff
2  | 1      | "mobile"     | important stuff
3  | 2      | "mobile"     | still relevant
4  | 3      | ""           | interesting

并要求为指定人员提取 1 个联系方法,并优先选择指定联系人类型的行(不是空字符串“”)。

当我需要获取一个人的contact_method 行时,我可以计算出如何获得正确答案。给我第 1 个人的联系方式:

SELECT * FROM contact_methods WHERE person = '1' ORDER BY contact_type DESC LIMIT 1;

这将导致 id 为 2 的行。

但我需要支持在单个查询中为每个人的列表获取一种联系方式的列表。例如。给我[1,2,3]人的结果

哪一个会产生 id 为 2、3 和 4 的行。有没有一种在一个查询中执行此操作的有效方法?

【问题讨论】:

不确定问题出在哪里。使用group by person,去掉LIMIT 1,改成WHERE person IN (1,2,3) 【参考方案1】:

在 Postgres 中,使用 DISTINCT ON:

SELECT DISTINCT ON (person) cm.* 
FROM contact_methods cm
WHERE person IN ('1', '2', '3')
ORDER BY person, contact_type DESC;

见:http://www.postgresqltutorial.com/postgresql-select-distinct/

【讨论】:

【参考方案2】:

您可以使用row_number() 窗口函数为每个人的每个方法分配一个从“最高”到“最低”方法的数字。空字符串是存在的“最低”字符串,因此它将在最后一个位置进行排序。从那里选择这样一个数字为 1 的行。如果一个人的非空方法存在,它将有一个 1。

SELECT id,
       person,
       contact_type,
       other_data
       FROM (SELECT id,
                    person,
                    contact_type,
                    other_data,
                    row_number() OVER (PARTITION BY person
                                       ORDER BY contact_type DESC) rn
                    FROM contact_methods
                    WHERE person IN (1,
                                     2,
                                     3)) x
       WHERE rn = 1;

【讨论】:

以上是关于SQL(Postgres)为列表参数中的每个项目获取一行,其优先顺序由另一列指定的主要内容,如果未能解决你的问题,请参考以下文章

将包含列表的记录值与 Postgres 中的列值进行比较

vb.net 为 datagridviewcombobox 中的每个项目显示工具提示文本

Postgres - 将列中的各种名称替换为相应的唯一标识符

我如何等待列表中的每个元素使用 cypress 更新为特定文本

为报表选择多个参数,如何在参数列表中为每个项目创建多个页面?

从java调用带有UDT参数的postgres函数给SQL尚未实现异常