Sql 匹配所有可能值的值(当然,空值除外)?

Sql 匹配所有可能值的值(当然,空值除外)?,sql,postgresql,Sql,Postgresql,postgresql中有没有什么技巧可以让一个值匹配所有可能的值,一种“一网打尽”的值,一种反空值 现在,我最好的办法是选择一个“catchall”关键字并在我的查询中强制匹配 WITH cities AS (SELECT * FROM (VALUES('USA','New York'), ('USA','San Francisco'), ('Can

postgresql中有没有什么技巧可以让一个值匹配所有可能的值,一种“一网打尽”的值,一种反空值

现在,我最好的办法是选择一个“catchall”关键字并在我的查询中强制匹配

WITH cities AS (SELECT * FROM (VALUES('USA','New York'),
                                     ('USA','San Francisco'),
                                     ('Canada','Toronto'),
                                     ('Canada','Quebec')
                               )x(country,city)),
     zones  AS (SELECT * FROM (VALUES('USA East','USA','New York'),
                                     ('USA West','USA','San Francisco'),
                                     ('Canada','Canada','catchall')
                               )x(zone,country,city))
SELECT z.zone, c.country, c.city
FROM cities c,zones z
WHERE c.country=z.country
  AND z.city IN (c.city,'catchall');

   zone   | country |     city
----------+---------+---------------
 USA East | USA     | New York
 USA West | USA     | San Francisco
 Canada   | Canada  | Toronto
 Canada   | Canada  | Quebec
如果在“城市”表中插入新的加拿大城镇,“分区”表将自动将其识别为“加拿大”分区的一部分。 上面的查询满足了我所寻找的功能,但是如果在广泛的数据库中重复多次,它会感觉很尴尬,并且容易出错

这是正确的方法吗?是有更好的方法吗?还是我问错了问题


非常感谢你的回答

我怀疑有这样的事情。一种简单但不十分优雅、高效或灵活的方法是定义函数
cities_equals(text t1,text t2)
,如果两者都不为null和(t1==t2或t1='catchall'或t2='catchall'),则该函数返回true

我个人认为
null
是一个更好的选择:

select z.zone, c.country, c.city
from cities c join
     zones z
     on c.country = z.country and
        (c.city = z.city or z.city is null);
甚至:

select z.zone, c.country, c.city
from cities c join
     zones z
     on c.country = z.country and
        c.city = coalesce(z.city, c.city);
根据丹尼斯的说法,Postgres似乎足够聪明,可以在第一次查询中为
国家
城市
使用索引

您还可以进行两部分联接,如果您在
区域(国家)
区域(国家、城市)
上都有索引,您可以进行两部分联接:

select coalesce(zcc.zone, zc.zone) as zone, c.country, c.city
from cities c join
     zones zcc
     on c.country = z.country and
        c.city = z.city join
     zones zc
     on c.country = z.country and
        zc.city is null;

虽然有点复杂,但两个联接都应该能够使用适当的索引。

将您的条件更改为与类似,并构造一个同时匹配这两个条件的正则表达式:

  and z.city similar to '(' || c.city || ')|(%)'

不确定我是否正确理解了需求,但是
其中c.country=z.country和(z.city in(c.city)或z.city为空)
会将特定国家的所有城市放在该国家的区域中,城市列中的值为null(在本例中,将“catchall”替换为null)。但是,只有当您计划将一个国家的所有城市都放在同一区域时,这才有用。在您的示例中,如果您添加了一个带有空城市的美国区域,那么纽约市和旧金山市最终都将位于东/西区域和新的空区域。是的,这也是一种可能性,您完全理解这些要求。我计划在一个包含许多类似连接查询的数据库中实现这一点,我正在寻找最优雅的解决方案。我忍不住想,如果能用一个简单的
select*from cities join zones使用(country,city)
获得我想要的结果,那该多好啊。写
catchall
(z.city=c.city或z.city='catchall'的可读性更强(但更长)一点的方式)
这个简单的
非空值是否做你想做的事?
非空值将使左侧的每个非空值与右侧的每一行匹配,因此它不会产生所需的结果。在这里,我试图找到一个值,其中右侧的指定行与左侧的每一行匹配。我还没有尝试过,但我认为Postgres将能够使用索引进行第一次查询。(
位图索引扫描
位图或
/
位图和
)。使用
不同于
将简化上述部分。使用
NULL
的唯一问题是它还匹配左侧的NULL值。因此,我想我可以使用
c.city=z.city或(z.city为null,c.city不为null)
“postgres不会对这些查询中的任何一个使用城市索引”--它将在第一个查询中使用位图索引扫描,并根据需要使用
两个单独索引扫描的结果。为了完整地回复删除的注释,请参阅,这将禁止任何postgres尝试使用
城市
字段上的索引(如果存在)。