选择性过滤列值不为空的行 PostgreSQL

Posted

技术标签:

【中文标题】选择性过滤列值不为空的行 PostgreSQL【英文标题】:Selectively filter rows where column value is not null PostgreSQL 【发布时间】:2020-11-21 07:58:40 【问题描述】:

我在 Postgres 11.0 中有下表。

col1        col2        col3                                                       col4             col5
1           NCT02582996 acetaminophen+caffeine+dihydroergotamine+metoclopramide.    metoclopramide. 204756
1           NCT02582996 acetaminophen+caffeine+dihydroergotamine+metoclopramide.    metoclopramide. null
3           NCT02582997 acetaminophen                                               metoclopramide. 204758
4           NCT02582998 ibuprufin                                                   ibuprufin       null

对于相同的 col1 值,我想只保留 col5 不为空的那些行。并丢弃另一行。

期望的输出是:

col1        col2        col3                                                       col4             col5
1           NCT02582996 acetaminophen+caffeine+dihydroergotamine+metoclopramide.    metoclopramide. 204756
3           NCT02582997 acetaminophen                                               metoclopramide. 204758
4           NCT02582998 ibuprufin                                                   ibuprufin       null
select * from tbl where col5 is not null  --excluding row 4

我不确定如何实现这一点。非常感谢任何帮助。

【问题讨论】:

只是想 SELECT 行,还是实际上 DELETE 不需要的行? 我更愿意选择它们。 那么:你的查询做你想做的事。 是否包括:4 NCT02582998 ibuprufin ibuprufin null 为什么要保留记录 4? 【参考方案1】:
CREATE TABLE tbl
        ( col1 integer
        , col2 text
        , col3 text
        , col4 text
        , col5 integer
        );
INSERT INTO tbl
VALUES
(1, 'NCT02582996', 'acetaminophen+caffeine+dihydroergotamine+metoclopramide.', 'metoclopramide.', 204756)
,(1, 'NCT02582996','acetaminophen+caffeine+dihydroergotamine+metoclopramide.', 'metoclopramide.',NULL)
,(3, 'NCT02582997','acetaminophen', 'metoclopramide.', 204758)
,(4, 'NCT02582998','ibuprufin',NULL,NULL)
        ;

select * from tbl t1;

select * from tbl t1
where col5 is not null
OR NOT EXISTS (
        select * from tbl x
        WHERE x.col1 = t1.col1
        and x.col5 is not null
        );

结果:


CREATE TABLE
INSERT 0 4
 col1 |    col2     |                           col3                           |      col4       |  col5  
------+-------------+----------------------------------------------------------+-----------------+--------
    1 | NCT02582996 | acetaminophen+caffeine+dihydroergotamine+metoclopramide. | metoclopramide. | 204756
    1 | NCT02582996 | acetaminophen+caffeine+dihydroergotamine+metoclopramide. | metoclopramide. |       
    3 | NCT02582997 | acetaminophen                                            | metoclopramide. | 204758
    4 | NCT02582998 | ibuprufin                                                |                 |       
(4 rows)

 col1 |    col2     |                           col3                           |      col4       |  col5  
------+-------------+----------------------------------------------------------+-----------------+--------
    1 | NCT02582996 | acetaminophen+caffeine+dihydroergotamine+metoclopramide. | metoclopramide. | 204756
    3 | NCT02582997 | acetaminophen                                            | metoclopramide. | 204758
    4 | NCT02582998 | ibuprufin                                                |                 |       
(3 rows)

【讨论】:

【参考方案2】:

我认为你可以使用distinct on:

select distinct on (col1) t.*
from tbl t
order by col1, col5

这仅在col1 中为每个不同的值生成一行。如果col1col5 中同时具有非nullnull 值,则保留非null 值。如果只有一行可用且具有null 值,则将其选中。

【讨论】:

要明确逻辑,您可以使用order by col1, col5 nulls last 个人认为 DISTINCT (ON) 是一个坏习惯,它就像是查询的皮质类固醇。

以上是关于选择性过滤列值不为空的行 PostgreSQL的主要内容,如果未能解决你的问题,请参考以下文章

JQ选择值包含字符串且值不为空的对象

如何在mysql中获取值不为null的列名

按列分组,优先选择另一列不为空的行

如果上一列值不为空,则更新表中的下一列

Python Pandas:获取列不为空的DataFrame的行

Firestore 选择不为空的位置