在反向 int 对中使用 DISTINCT 重复消除
Usage of DISTINCT in reversed int pairs duplicates elimination
我有以下问题:
create table memorization_word_translation
(
id serial not null
from_word_id integer not null
to_word_id integer not null
);
这个 table 存储整数对,它们通常以相反的顺序排列,例如:
35 36
35 37
36 35
37 35
37 39
39 37
问题是 - 如果我进行查询,例如:
select * from memorization_word_translation
where from_word_id = 35 or to_word_id = 35
我会得到
35 36
35 37
36 35 - duplicate of 35 36
37 35 - duplicate of 35 37
这个例子中如何使用DISTINCT来过滤掉所有的重复项,即使它们被颠倒了?
我只想像这样保留它:
35 36
35 37
您可以使用 ROW_NUMBER() window 函数:
select from_word_id, to_word_id
from (
select *,
row_number() over (
partition by least(from_word_id, to_word_id),
greatest(from_word_id, to_word_id)
order by (from_word_id > to_word_id)::int
) rn
from memorization_word_translation
where 35 in (from_word_id, to_word_id)
) t
where rn = 1
参见demo。
您可以结合 DISTINCT ON
.
尝试使用小型排序算法(此处为比较)
DISTINCT ON
子句适用于任意列或术语,例如在元组上。此 CASE 子句将两列排序为元组并删除绑定的(有序的)元组。可以在 SELECT 语句中返回源列:
select distinct on (
CASE
WHEN (from_word_id >= to_word_id) THEN (from_word_id, to_word_id)
ELSE (to_word_id, from_word_id)
END
)
*
from memorization_word_translation
where from_word_id = 35 or to_word_id = 35
我有以下问题:
create table memorization_word_translation
(
id serial not null
from_word_id integer not null
to_word_id integer not null
);
这个 table 存储整数对,它们通常以相反的顺序排列,例如:
35 36
35 37
36 35
37 35
37 39
39 37
问题是 - 如果我进行查询,例如:
select * from memorization_word_translation
where from_word_id = 35 or to_word_id = 35
我会得到
35 36
35 37
36 35 - duplicate of 35 36
37 35 - duplicate of 35 37
这个例子中如何使用DISTINCT来过滤掉所有的重复项,即使它们被颠倒了? 我只想像这样保留它:
35 36
35 37
您可以使用 ROW_NUMBER() window 函数:
select from_word_id, to_word_id
from (
select *,
row_number() over (
partition by least(from_word_id, to_word_id),
greatest(from_word_id, to_word_id)
order by (from_word_id > to_word_id)::int
) rn
from memorization_word_translation
where 35 in (from_word_id, to_word_id)
) t
where rn = 1
参见demo。
您可以结合 DISTINCT ON
.
DISTINCT ON
子句适用于任意列或术语,例如在元组上。此 CASE 子句将两列排序为元组并删除绑定的(有序的)元组。可以在 SELECT 语句中返回源列:
select distinct on (
CASE
WHEN (from_word_id >= to_word_id) THEN (from_word_id, to_word_id)
ELSE (to_word_id, from_word_id)
END
)
*
from memorization_word_translation
where from_word_id = 35 or to_word_id = 35