问题:在树状表中选择数据并回退到默认值的最佳方法

我有一个应用程序需要基于某些字段的参数。如果未找到特定字段,则应用程序应获取不太特定的参数值:

+----+-------+-------+------+--------------------------------------+
|PAR | ColA  | ColB  | ColC | value                                |
+----+-------+-------+------+--------------------------------------+
|Par1| *     | *     | *    | (this is the default value)  99      |
+----+-------+-------+------+--------------------------------------+
|Par1| ValA1 | *     | *    | (in case no valid ColB+ColC) 100     |
+----+-------+-------+------+--------------------------------------+
|Par1| ValA1 | ValB1 | *    | (in case no valid ColC)      200     |
+----+-------+-------+------+--------------------------------------+
|Par1| ValA1 | ValB1 | ValC1| (in case everything is specified) 333|
+----+-------+-------+------+--------------------------------------+

所以一个用户请求:

“Par1”的 ValA1、ValB1、ValC1 -> 将得到“333”

而用户请求:

“Par1”的 ValA1,ValB1,ValX -> 将得到“200”。

我可以使用一组查询或 UNION 轻松地做到这一点(首先查找所有 cols,而不是查找 ColCu003d'',然后使用 ColBu003d'' 和 ColCu003d'*' 等等)但是在那里更好的方法?

例子:

select value from mytab where PAR='Par1' and ColA='ValA1' and ColB='ValB1' and ColC='ValC1' 
UNION
select value from mytab where PAR='Par1' and ColA='ValA1' and ColB='ValB1' and ColC='*' 
UNION
select value from mytab where PAR='Par1' and ColA='ValA1' and ColB='*' and ColC='*' 
UNION
select value from mytab where PAR='Par1' and ColA='*' and ColB='*' and ColC='*' 

然后得到列最多的“值”!u003d'*'

我正在使用 Postgresql,但如果有帮助的话,我愿意使用不同的数据库。

LTREE会在这里帮助吗?

编辑: 表可能非常大(数百万条记录)。因此,通过“PAR”选择只能返回一个非常大(大部分无用)的结果集,并且不如选择正确的行那么快......

解答

select value 
from mytab 
where PAR='Par1' 
ORDER BY
   CASE WHEN ColA='ValA1' and ColB='ValB1' and ColC='ValC1' THEN 0 else 1 END ASC,
   CASE WHEN ColA='ValA1' and ColB='ValB1' THEN 0 else 1 END ASC,
   CASE WHEN ColA='ValA1' THEN 0 else 1 END ASC
LIMIT 1

您可以按表达式添加排序并获得第一名。

更新:

您可以添加到 WHERE 部分

AND (ColA='ValA1' or ColA='*')
AND (ColB='ValB1' or ColB='*')
AND (ColC='ValC1' or ColC='*')

甚至更复杂的情况

AND (
   (ColA='ValA1' and ColB='ValB1' and ColC='ValC1')
   OR
   (ColA='ValA1' and ColB='ValB1' and ColC='*')
   OR
   (ColA='ValA1' and ColB='*' and ColC='*')
   OR
   (ColA='*' and ColB='*' and ColC='*')
)
Logo

PostgreSQL社区为您提供最前沿的新闻资讯和知识内容

更多推荐