【问题标题】:Postgres select distinct of cartesian productPostgres 选择不同的笛卡尔积
【发布时间】:2017-12-14 02:01:32
【问题描述】:

如何从两列中选择每个值只显示一次?

例如。从此表:

Column A                             Column B
-------------------------------------------------------------------------
02131d36-06cc-408e-9e40-1de65fbf37f4 7495fc05-e244-426c-bdae-a5ee121be510
11c32339-1b77-46e1-9215-0b1d4ec0b1d3 7495fc05-e244-426c-bdae-a5ee121be510
39cb3ebd-bb7f-4023-ab44-65a0f3e4d6d2 7b9fb1b0-61d4-4424-af83-33b1b7e77bc1
39cb3ebd-bb7f-4023-ab44-65a0f3e4d6d2 7495fc05-e244-426c-bdae-a5ee121be510
94e66d74-f0ce-472b-ad68-a98e267038b8 7495fc05-e244-426c-bdae-a5ee121be510
ab8130c7-e6a3-46cc-9ebc-0f8aca698169 7b9fb1b0-61d4-4424-af83-33b1b7e77bc1
ab8130c7-e6a3-46cc-9ebc-0f8aca698169 7495fc05-e244-426c-bdae-a5ee121be510
94e66d74-f0ce-472b-ad68-a98e267038b8 7b9fb1b0-61d4-4424-af83-33b1b7e77bc1
02131d36-06cc-408e-9e40-1de65fbf37f4 c597af82-58d5-4630-87e5-939898cc68ed
11c32339-1b77-46e1-9215-0b1d4ec0b1d3 c597af82-58d5-4630-87e5-939898cc68ed
39cb3ebd-bb7f-4023-ab44-65a0f3e4d6d2 c597af82-58d5-4630-87e5-939898cc68ed
ab8130c7-e6a3-46cc-9ebc-0f8aca698169 c597af82-58d5-4630-87e5-939898cc68ed
94e66d74-f0ce-472b-ad68-a98e267038b8 c597af82-58d5-4630-87e5-939898cc68ed

拉出这个(A和B都不同):

02131d36-06cc-408e-9e40-1de65fbf37f4 7495fc05-e244-426c-bdae-a5ee121be510
ab8130c7-e6a3-46cc-9ebc-0f8aca698169 7b9fb1b0-61d4-4424-af83-33b1b7e77bc1
94e66d74-f0ce-472b-ad68-a98e267038b8 c597af82-58d5-4630-87e5-939898cc68ed

我知道有几种可能的组合,我想要任何一种其中之一,但不是全部。

该表由 B 的不同值和 A 的不同值的笛卡尔积的子集组成。

我一直在干预窗口函数和分组依据,但还没有让它工作。

【问题讨论】:

  • 我可能会去看看 DISTINCT ON。
  • A 列中的“39cb3ebd-bb7f-4023-ab44-65a0f3e4d6d2”和“11c32339-1b77-46e1-9215-0b1d4ec0b1d3”在哪里?我期待更多的记录。还是我错了?
  • 哦,还有第三列,它们被过滤掉了!我应该说它只是笛卡尔积的一个子集。

标签: sql postgresql distinct distinct-values distinct-on


【解决方案1】:

使用窗口函数:

t=# create table so182(a text,b text);
CREATE TABLE
Time: 23.926 ms
t=# copy so182 from stdin delimiter ' ';
t=# select distinct first_value(a) over (partition by b),b from so182;
             first_value              |                  b
--------------------------------------+--------------------------------------
 02131d36-06cc-408e-9e40-1de65fbf37f4 | 7495fc05-e244-426c-bdae-a5ee121be510
 11c32339-1b77-46e1-9215-0b1d4ec0b1d3 | c597af82-58d5-4630-87e5-939898cc68ed
 39cb3ebd-bb7f-4023-ab44-65a0f3e4d6d2 | 7b9fb1b0-61d4-4424-af83-33b1b7e77bc1
(3 rows)

区别于:

t=# select distinct on (b) b,a from so182;
                  b                   |                  a
--------------------------------------+--------------------------------------
 7495fc05-e244-426c-bdae-a5ee121be510 | 02131d36-06cc-408e-9e40-1de65fbf37f4
 7b9fb1b0-61d4-4424-af83-33b1b7e77bc1 | 39cb3ebd-bb7f-4023-ab44-65a0f3e4d6d2
 c597af82-58d5-4630-87e5-939898cc68ed | 11c32339-1b77-46e1-9215-0b1d4ec0b1d3
(3 rows)

Time: 0.263 ms

【讨论】:

  • 如果你尝试用结果,不会有以前那样的数据了
  • 如果我理解 OP,任何 A 行都意味着我们想要任何一个,所以其余的都会丢失,这是需要的。也许我没看懂帖子?..
  • 我之前尝试过 distinct on (b) 方法,但有时它会在 a 列中给出重复项,所以不是这样......它可能会给出:c597af82-58d5-4630-87e5-939898cc68ed , 02131d36-06cc-408e-9e40-1de65fbf37f4,这是 A 列中的重复项
  • @Eric true - 如果我用order by 指定订单,它肯定会这样做:)
  • 抱歉 - 从帖子中不清楚 A 列中的值应该是不同的 - 我认为任何 A 都可以
【解决方案2】:

抱歉,我现在无法检查它是否有效,但是如何:

  1. 创建 2 个临时表,例如:

    CREATE TABLE #ColumnA(id int NOT NULL AUTO_INCREMENT, columna varchar(30))
    CREATE TABLE #ColumnB(id int NOT NULL AUTO_INCREMENT, columnb varchar(30))
    
  2. 像这样填充它们:

     INSERT INTO ColumnA SELECT DISTINCT columna FROM OriginalTable
     INSERT INTO ColumnB SELECT DISTINCT columnb FROM OriginalTable
    
  3. 加入:

    SELECT a.columna, b.columnb FROM ColumnA a OUTER JOIN ColumnB b ON a.id = b.id
    

它不漂亮,但应该可以。在第 1 点中,我用 # 写了表名 - 它似乎是在创建临时表。 AUTO_INCREMENT 在不同的 dbms 中也可能不同(在 postgres 中,“id serial”对于本专栏来说就足够了)。 如果没有更好的答案,我可以稍后再查看。

【讨论】:

    猜你喜欢
    • 2014-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-06
    • 1970-01-01
    • 2011-04-21
    相关资源
    最近更新 更多