Sql 匹配所有可能值的值(当然,空值除外)?
postgresql中有没有什么技巧可以让一个值匹配所有可能的值,一种“一网打尽”的值,一种反空值 现在,我最好的办法是选择一个“catchall”关键字并在我的查询中强制匹配Sql 匹配所有可能值的值(当然,空值除外)?,sql,postgresql,Sql,Postgresql,postgresql中有没有什么技巧可以让一个值匹配所有可能的值,一种“一网打尽”的值,一种反空值 现在,我最好的办法是选择一个“catchall”关键字并在我的查询中强制匹配 WITH cities AS (SELECT * FROM (VALUES('USA','New York'), ('USA','San Francisco'), ('Can
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尝试使用城市
字段上的索引(如果存在)。