Postgresql 如果行是唯一的,如何选择行?

Postgresql 如果行是唯一的,如何选择行?,postgresql,Postgresql,我尝试执行一个由两部分组成的查询,并返回一个由分号分隔的列值组成的文本数组 首先,根据三列的值仅选择唯一的行,即如果三个值元组存在多次,则它不是唯一的。在剩余行中,根据第四列执行另一个文件管理器 这就是我的想法,但也许有更好的解决办法 我试过几种不同的方法。我当前的尝试是使用CTE: with uniqe as ( select distinct on ( col1, col2, col3 ) * from MyTable

我尝试执行一个由两部分组成的查询,并返回一个由分号分隔的列值组成的文本数组

首先,根据三列的值仅选择唯一的行,即如果三个值元组存在多次,则它不是唯一的。在剩余行中,根据第四列执行另一个文件管理器

这就是我的想法,但也许有更好的解决办法

我试过几种不同的方法。我当前的尝试是使用CTE:

with uniqe as (
    select distinct on (
        col1,
        col2,
        col3
    ) *
    from MyTable
)
select concat(col::text, ';', col2::text, ';', col3)
    as key
    from uniqe
    where upper(dateRange) <= (now() - interval '1 days')
    order by key;

我认为行3和4是唯一的行。 本质上,问题归结为基于聚合或窗口函数的值选择行。 因此,除我们希望count*等于1的情况外,其他情况都适用

因此,我们可以使用:

或:

正如所述,分区方式与分组方式在影响窗口函数的 结果是CalculateIOD,但与GROUP BY不同,它不影响 返回行。

我必须将dateRange列添加到select语句中,但仅此而已。如果您更新了答案,我会将其作为所选答案。非常感谢。我必须仔细阅读表分区,因为我不能100%确定这里发生了什么
 id  | col1 | col2 | col3 |                       dateRange
-----+------+------+------+-------------------------------------------------------
  1  |   1  |   1  |  A   |   ["2018-12-31 16:01:40-08","2018-12-31 16:03:20-08")
  2  |   1  |   1  |  A   |   ["2018-12-31 16:01:40-08","2018-12-31 16:03:20-08")
  3  |   1  |   1  |  B   |   ["2018-12-31 16:01:40-08","2018-12-31 16:03:20-08")
  4  |   1  |   2  |  A   |   ["2018-12-31 16:01:40-08","2018-12-31 16:03:20-08")
  5  |   2  |   1  |  A   |   ["2018-12-31 16:01:40-08","2018-12-31 16:03:20-08")
  6  |   2  |   1  |  A   |   ["2018-12-31 16:01:40-08","2018-12-31 16:03:20-08")
  7  |   1  |   2  |  B   |   ["2018-12-31 16:01:40-08","2018-12-31 16:03:20-08")
  8  |   1  |   2  |  B   |   ["2018-12-31 16:01:40-08","2018-12-31 16:03:20-08")
WITH uniqe AS (
    SELECT *
    FROM MyTable
    WHERE (col1, col2, col3) IN (
        SELECT col1, col2, col3
        FROM MyTable
        GROUP BY col1, col2, col3
        HAVING count(*) = 1
    ) AS t
)    
WITH uniqe AS (
    SELECT *
    FROM (
        SELECT col1, col2, col3, dateRange
            , count(*) OVER (PARTITION BY col1, col2, col3) AS cnt
        FROM MyTable
    ) AS t
    WHERE cnt = 1
)