有没有办法在不硬编码位串宽度0的情况下进行非零位串测试?
例如,假设我有两个表,用户和功能,每个表都有掩码,我想测试一下:
SELECT u.name FROM Users u, Features f
WHERE u.mask & f.mask;
匹配隐式非零结果。但是,SQL 需要显式布尔结果WHERE
与隐式强制转换相反,如下所示:
SELECT u.name FROM Users u, Features f
WHERE (u.mask & f.mask) != 0::BIT(2048);
我不想硬编码2048
(或其他)出于多种原因在此查询中。
Testing expr = 0
or expr > 0
导致类型错误。奇怪的是,我可以测试expr = 0::BIT(1)
,但这给出了错误的答案,因为 Postgres 并不认为所有全零位字符串都是相等的。
select 0::BIT(2) > 0::BIT(1);
?column?
----------
t
(1 row)
我可以通过这样做创建一个计算的零:
SELECT u.name FROM Users u, Features f
WHERE (u.mask & f.mask) != (u.mask & ~u.mask);
这可行,但感觉像是一个糟糕的黑客。
有什么建议或见解吗?
RESULTS
我对下面提供的几个选项进行了基准测试。感谢您的建议,埃尔文!
基于非常大的数据集和 100,000 个查询,我发现以下构造导致每秒关联的查询数。希望 Postgres 团队的有人看到这一点并提供通用 0 来加快速度!不幸的是,大多数通用方法似乎都会产生相当昂贵的字符串转换。
Constructs | Queries / s
----------------------------------------+--------------
(u.mask & f.mask) <> 0::BIT(2048) | 158
(u.mask & f.mask) <> (u.mask # u.mask) | 135
(u.mask & f.mask) <> (u.mask & ~u.mask) | 125
position('1' IN (u.mask & f.mask)) > 0 | 37
(u.mask & f.mask)::TEXT !~ '^0+$' | 27