PostgreSQL-在case语句中为字符串指定整数值

PostgreSQL-在case语句中为字符串指定整数值,sql,postgresql,Sql,Postgresql,我需要根据我拥有的数据中的ID选择一行且仅选择一行数据。我认为我已经解决了这个问题(有关详细信息,请参阅我的原始问题和解决方案,此处:) 但是,在某些情况下,我现在仍然会得到多个值。如果只有“N/A”和1个其他值,则没有问题。。但如果我有多个值,例如:“N/A”、“value1”和“value2”,那么我的案例陈述是不够的,我得到了“value1”和“value2”返回给我。这是有关的案例陈述: CASE WHEN "PQ"."Value" = 'N/A' THEN 1 ELSE

我需要根据我拥有的数据中的ID选择一行且仅选择一行数据。我认为我已经解决了这个问题(有关详细信息,请参阅我的原始问题和解决方案,此处:)

但是,在某些情况下,我现在仍然会得到多个值。如果只有“N/A”和1个其他值,则没有问题。。但如果我有多个值,例如:“N/A”“value1”“value2”,那么我的案例陈述是不够的,我得到了“value1”“value2”返回给我。这是有关的案例陈述:

CASE
    WHEN "PQ"."Value" = 'N/A' THEN 1
    ELSE 0
END
我需要给每个字符串值一个唯一的整数值,然后问题就解决了。问题是:我如何做到这一点?我的第一个想法是以某种方式将字符值转换为ASCII码,并将它们相加。。但我不知道如何做到这一点,也担心表现。有没有一种方法可以非常简单地为每个字符串指定一个值,这样我就只能选择一个值?我不在乎到底是哪一个。。。只不过是1

编辑


我现在尝试创建一个函数,将每个字符的ASCII值相加,这样我就可以将我的case语句更改为如下内容:

CASE
    WHEN "PQ"."Value" = 'N/A' THEN 9999999
    ELSE SumASCII("PQ"."Value")
END
但是有个小问题。。我把它作为一个单独的问题补充到这里:

编辑2

感谢@Bohemian,我现在有了一个有效的解决方案,如下所示:

CASE
    WHEN "PQ"."Value" = 'N/A' THEN -1
    ELSE ('x'||LPAD(MD5("PQ"."Value"),16,'0'))::bit(64)::bigint
END DESC

如果您不关心选取哪个值,请将RANK()更改为ROW_NUMBER()。如果您真的在意,尽管这样做,但也可以在CASE语句后添加另一个术语,以逗号分隔,并使用您想要的逻辑-例如,如果您想要按字母顺序排列第一个值,请执行以下操作:

...
ORDER BY CASE...END, "PQ"."Value")
...
这将为每个值生成一个“唯一”编号:

('x'||substr(md5("PQ"."Value"),1,8))::bit(64)::bigint
严格地说,有可能发生碰撞,但这是非常遥远的

如果结果“太大”,您可以尝试:

<above-calculation> % 10000
%10000

尽管发生碰撞的几率为0.01%,但您应该针对所有已知值尝试此公式,以确保没有碰撞。

谢谢。问题是,我不知道这些价值观是什么。基本上,我想要这样的逻辑:如果只有“N/A”,那么返回那个。。。如果还有其他值,则返回任何不是“N/A”的值。如果我按照你的建议下订单,有时我可能会在不需要时得到“不适用”。这就是为什么我使用CASE语句将“N/A”的值设置为1,其他值设置为0。。当然,多个值得到0,我得到多个值,而不是只返回1。非常令人沮丧。我现在正在尝试创建一个函数,将每个字符的ASCII值相加,这样我就可以将case语句改为这样的内容:
case WHEN“PQ.”Value“='N/a'然后999999 ELSE sumscii(“PQ”。.Value”)END
。。但是有个小问题。。如果你愿意,你可以在这里看到:请把它改成ROW_NUMBER()-我真的认为这对你有用。谢谢,但是,我刚刚试过,当我有'N/A'和'popup',并且改成ROW_NUMBER(),而不是RANK(),那么我只得到'N/A',这是不正确的。如果你在上面使用完整表达式ROW_NUMBER()(按B.ID顺序按大小写划分,当“PQ”。“Value”=“N/A”然后1或0结束,“PQ”。“Value”)除非数据与您最初声明的不同,否则您确实不应该得到“N/A”。这不起作用。
md5()
返回一个无法转换为整数的十六进制值。尝试按照您的建议执行操作时,我遇到的错误如下:运算符不存在:text%integer。这只是一个简单的测试:
选择md5('email')%10000
@matt oops。请立即尝试。谢谢。两件事:1.您缺少开始括号('.2.我也在研究一个类似的解决方案,它是:
('x'| | LPAD(MD5(“PQ.”Value),16,'0'))::位(64)::bigint
你的和这个产生的值略有不同。知道区别是什么吗?@Matt MD5返回一个十六进制字符串,它没有前导零。另一个代码保证16个十六进制字符(64位),以防md5太小,以至于没有足够的位用于强制转换,这种可能性很小(但可能)。