3

postgresql 中是否有任何技巧可以使值匹配每个可能的值,一种“Catch all”值,一种反 NULL ?

现在,我最好的想法是选择一个“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

如果在“城市”表中插入一个新的加拿大城镇,“区域”表将自动将其识别为“加拿大”区域的一部分。上面的查询满足了我正在寻找的功能,但是如果在一个广泛的数据库中重复多次,它会感觉很尴尬并且容易出错。

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

非常感谢你的回答!

4

3 回答 3

1

就个人而言,我认为这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);

根据 Denis 的说法,Postgres 似乎足够聪明,可以在第一次查询时使用索引来处理countrycity.

你也可以做一个两部分连接,如果你在 bothzone(country)和 on 上有索引zone(country, city),你可以做一个两部分连接:

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;

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

于 2013-06-05T21:32:30.917 回答
0

我怀疑是否有类似的东西。一个简单但不是很优雅、高效或灵活的方法是定义你的函数cities_equals(text t1, text t2) ,如果两者都不为空并且( t1 == t2 OR t1 == 'catchall' OR t2 == 'catchall'),则返回 true

于 2013-06-05T21:08:59.653 回答
0

将您的条件更改为 SIMILAR TO 并构造一个匹配两者的正则表达式:

  and z.city similar to '(' || c.city || ')|(%)'
于 2013-06-05T21:40:16.117 回答