如何选择唯一的行?

时间:2019-02-12 03:44:12

标签: postgresql

我正在尝试进行两部分查询,并返回以分号分隔的列值的文本数组。

首先,仅根据三列的值选择唯一的行(即,如果三个值的元组存在多次,则它不是唯一的)。在其余的行中,根据第四列执行另一个过滤器。

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

我已经尝试了几种不同的方法。我目前的尝试是使用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;

我遇到的问题是,SELECT DISTINCT ON (col1, col2, col3) ...似乎从我不认为“唯一”的其他行中至少选择了一行。

请清楚,这是一个示例表:

 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")

我认为第3和第4行是唯一的唯一行。

1 个答案:

答案 0 :(得分:1)

从本质上讲,问题归结为根据聚合或窗口函数的值选择行。 因此solutions here是适用的,除了在我们的情况下,我们希望count(*)等于1。

因此,我们可以使用WHERE IN method

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
)    

PARTITION BY method

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
)    

Andomar explains一样,PARTITION BYGROUP BY的相似之处在于它影响窗口函数的方式 计算结果,但与GROUP BY不同,它不会影响 返回的行。