【问题标题】:SELECT DISTINCT rows that can occur only onceSELECT DISTINCT 只能出现一次的行
【发布时间】:2021-05-28 21:14:36
【问题描述】:

假设我们使用左连接或内连接通过某种条件连接两个表(A 和 B)

WITH
a(id, x) AS (VALUES
    (0, 'a'),
    (1, 'a'),
    (2, 'b')
),
b(id, y) AS (VALUES
    (10, 'a'),
    (20, 'a'),
    (30, 'b')
),
pairs AS (
    SELECT a.id AS a_id, b.id AS b_id
    FROM a LEFT JOIN b ON a.x=b.y
)
SELECT * FROM pairs; -- how to modify this query to return the expected result?

结果将是 5 行 (2 * 2 + 1 * 1) 现在最困难的部分是:每个表中的 id 只能在结果中出现一次。

a_id|b_id|
----|----|
   0|  10|
 ->0|  20| -- a_id=0 can be picked only once
   1|->10| -- b_id=10 can be picked only once
   1|  20|
   2|  30|

-- so the expected result is:
a_id|b_id|
----|----|
   0|  10|
   1|  20|
   2|  30|

-- UPDATE: alternative result could be:
a_id|b_id|
----|----|
   0|  20|
   1|  10|
   2|  30|

【问题讨论】:

  • 我尝试使用子查询和DISTINCT ON 语法,但这并没有给我预期的结果
  • 为什么不(0,20),(1,10),(2,30)
  • 这是另一个满足结果的选项。取决于顺序,但总的来说没关系。只是 ID 不能重复
  • 我会更改配对的代码。这可能吗?
  • @S-Man 是的,但这有什么不同吗?

标签: postgresql join distinct distinct-values


【解决方案1】:

demo:db<>fiddle

加入表格后非常困难,我没有找到快速的解决方案。我想,这是一个组合问题,因为结果取决于您处理数据的顺序。但是如果数据发生变化,结果就完全不同了……也许有人证明我错了……

但是,如果我们能够在加入之前修改表,那就更好了:

WITH
a(id, x) AS (VALUES
    (0, 'a'),
    (1, 'a'),
    (2, 'b')
),
b(id, y) AS (VALUES
    (10, 'a'),
    (20, 'a'),
    (30, 'b')
),
pairs AS (
    SELECT a.id AS a_id, b.id AS b_id
    FROM (
        SELECT
            *,
            row_number() OVER (PARTITION BY x)
        FROM
            a
    ) a
    LEFT JOIN (
        SELECT
            *,
            row_number() OVER (PARTITION BY y)
        FROM
            b
    ) b ON a.x=b.y AND a.row_number = b.row_number
)
SELECT 
    *
FROM pairs

现在我们可以添加行数。所以我们可以合并数据和行数。这样可以确保每个数据只合并一次。

【讨论】:

  • 谢谢,有一个非常相似的解决方案,但需要检查它是否涵盖其他情况sql pairs AS ( SELECT a.id AS a_id, b.id AS b_id FROM a LEFT JOIN b ON a.x=b.y ), sub AS ( SELECT *, rank() OVER (PARTITION BY a_id ORDER BY b_id) rank_a, rank() OVER (PARTITION BY b_id ORDER BY a_id) rank_b FROM pairs ) SELECT * FROM sub WHERE rank_a = rank_b;
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-23
  • 1970-01-01
相关资源
最近更新 更多