假设PostgreSQL表articles
包含name
和alt_name
这两个可为空的String列。
*字符串name
和alt_name
的组合与同一表中相同类型的另一个组合匹配:
- 即
[a.name, a.alt_name]
等于[b.name, b.alt_name]
或[b.alt_name, b.name]
- 其中
name
或alt_name
可以是NULL
或空String,并且在任何情况下NULL
和空String都应被视为相同; - 例如,当
[a.name, a.alt_name] == ["abc", NULL]
时,[b.name, b.alt_name] == ["", "abc"]
的记录应该匹配,因为其中一个是"abc"
,另一个是NULL或空字符串。
有什么简洁的查询可以实现这一点吗?
我想,如果有一种方法可以将两列连接起来,中间使用UTF-8 * 替换字符 *(U+FFFD
),其中NULL被转换为空字符串,那么这个问题就可以解决了。比如,如果函数是magic_fn()
,那么下面的代码就可以完成工作,前提是存在一个唯一的列id
:
SELECT * FROM articles a INNER JOIN places b ON a.id <> b.id
WHERE
magic_fn(a.name, a.alt_name) = magic_fn(b.name, b.alt_name)
OR magic_fn(a.name, a.alt_name) = magic_fn(b.alt_name, b.name);
-- [EDIT] corrected from the original post, which was simply wrong.
但是,concatnation is not a built-in function in PostgreSQL又不知道如何做到这一点。
[EDIT]正如@Serg和回答中所评论的,从版本9.1(CONCAT or ||)开始,PostgreSQL中现在提供了一个字符串连接函数;注意,它实际上接受非字符串输入,只要其中一个是Ver.15的字符串类型。
或者,也许根本就有更好的办法?
5条答案
按热度按时间6jjcrrmo1#
您可以创建一个函数,该函数接受
name
和alt_name
,然后返回一个聚合字符串,其中null
转换为空字符串,并对结果进行排序:用法:
See fiddle
rsl1atfo2#
试试这个
db<>fiddle
vecaoik13#
回顾了几个答案(特别感谢@MitkoKeckaroski),我想出了这个简短的解决方案。COALESCE()没有必要!
条件是UTF取代字符(
\U+FFFD
)不应该出现在数据记录中,您可以根据Unicode规格放心地假设这一点。请参见db<>fiddle(我在这里扩展了@Ajax1234准备的数据--谢谢!)
b4lqfgs44#
您可以尝试使用
然后比较类似sql:
oxf4rvwz5#
您可以从这两个名称建立数组,移除null和空值,然后检查数组是否重叠(具有共同的元素)
通过创建一个生成这样的数组的函数,可以使这一点变得更容易:
通过设置参数
variadic
,可以提供不同数量的参数(理论上甚至多于两个)