在没有临时表的情况下,如何在postgresql中执行成本最低的路由查询?

在没有临时表的情况下,如何在postgresql中执行成本最低的路由查询?,postgresql,Postgresql,如何在PostgreSQL中执行电信最低成本路由查询? 其目的是生成一个结果集,该结果集按运营商的最低价格排序。表结构如下所示 例如,要检查通过特定运营商id传递的呼叫的成本,查询为: SELECT trf_price, trf_prefix as lmp FROM tariffs WHERE SUBSTRING(dialled_number,1, LENGTH(trf_prefix)) = trf_prefix and trf_carrier_id = carrier_id ORDER B

如何在PostgreSQL中执行电信最低成本路由查询? 其目的是生成一个结果集,该结果集按运营商的最低价格排序。表结构如下所示

例如,要检查通过特定运营商id传递的呼叫的成本,查询为:

SELECT trf_price, trf_prefix as lmp FROM tariffs WHERE SUBSTRING(dialled_number,1, LENGTH(trf_prefix)) = trf_prefix and trf_carrier_id = carrier_id  ORDER BY trf_prefix DESC limit 1
-- select * from tariffs
select distinct banana2.longest_prefix, banana2.trf_carrier_id_2, apple2.trf_carrier_id, apple2.lenprefix, apple2.trf_price, apple2.trf_destination from 
(select banana.longest_prefix, banana.trf_carrier_id_2 from (select  max(length(trf_prefix)) as longest_prefix, trf_carrier_id as trf_carrier_id_2 from  (select *, length(trf_prefix) as lenprefix from tariffs where substring('35567234567', 1, length(trf_prefix) )= trf_prefix) as apple group by apple.trf_carrier_id) as banana) as banana2,

(select *, length(trf_prefix) as lenprefix from tariffs where substring('35567234567', 1, length(trf_prefix) )= trf_prefix) as apple2 -- group by apple2.trf_carrier_id where banana2.trf_carrier_id_2=apple2.trf_carrier_id and banana2.longest_prefix=apple2.lenprefix order by trf_price
对于每个运营商的通话成本,即最低成本查询,查询为:

SELECT trf_price, trf_prefix as lmp FROM tariffs WHERE SUBSTRING(dialled_number,1, LENGTH(trf_prefix)) = trf_prefix and trf_carrier_id = carrier_id  ORDER BY trf_prefix DESC limit 1
-- select * from tariffs
select distinct banana2.longest_prefix, banana2.trf_carrier_id_2, apple2.trf_carrier_id, apple2.lenprefix, apple2.trf_price, apple2.trf_destination from 
(select banana.longest_prefix, banana.trf_carrier_id_2 from (select  max(length(trf_prefix)) as longest_prefix, trf_carrier_id as trf_carrier_id_2 from  (select *, length(trf_prefix) as lenprefix from tariffs where substring('35567234567', 1, length(trf_prefix) )= trf_prefix) as apple group by apple.trf_carrier_id) as banana) as banana2,

(select *, length(trf_prefix) as lenprefix from tariffs where substring('35567234567', 1, length(trf_prefix) )= trf_prefix) as apple2 -- group by apple2.trf_carrier_id where banana2.trf_carrier_id_2=apple2.trf_carrier_id and banana2.longest_prefix=apple2.lenprefix order by trf_price
查询工作的基础是,对于每个运营商,拨号号码的最长匹配前缀是唯一的,并且将是最长的。因此,选择中包含最长前缀和载波的联接将为所有载波提供集合

我的查询有一个问题:

我不想做两次apple(X)查询

(select *, length(trf_prefix) as lenprefix from tariffs where substring('35567234567', 1, length(trf_prefix) )= trf_prefix) as apple
必须有一种更优雅的方式,可能一次声明,两次使用

我要做的是为每个运营商在单个运营商上运行查询:

SELECT trf_price, trf_prefix as lmp FROM tariffs WHERE SUBSTRING(dialled_number,1, LENGTH(trf_prefix)) = trf_prefix and trf_carrier_id = carrier_id  ORDER BY trf_prefix DESC limit 1
并将它们组合成一组,按价格排序

事实上,我想将该方法推广到任何这样的查询中,其中特定列或列集的各种值的输出被合并到一个集合中以供进一步查询。我被告知CTE是完成此类查询的方法,但我发现文档相当混乱。使用您自己的用例要容易得多


另外,我知道前缀长度可以预先计算和存储。

通用表表达式:

with apple as (
 select *, length(trf_prefix) as lenprefix
   from tariffs
  where substring('35567234567', 1, length(trf_prefix)) = trf_prefix
)
select distinct banana2.longest_prefix, banana2.trf_carrier_id_2,
       apple.trf_carrier_id, apple.lenprefix, apple.trf_price,
       apple.trf_destination
from (select banana.longest_prefix, banana.trf_carrier_id_2
        from (select max(length(trf_prefix)) as longest_prefix,
                     trf_carrier_id as trf_carrier_id_2
                from apple
              group by apple.trf_carrier_id) as banana) as banana2,
     apple
where banana2.trf_carrier_id_2 = apple.trf_carrier_id
  and banana2.longest_prefix = apple.lenprefix
order by trf_price

您只需拉出重复的表定义即可。即使我一次只使用了这些子选择中的一个,我仍然使用CTE。我发现您使用的样式基本上不可读。

您在这里尝试了什么:
子字符串(前缀,1,长度(前缀))
?如果你把
carrier\u id
的部分放在
WHERE
中,你就会得到答案。@JakubKania查询中有一个错误,应该是
SELECT cost,prefix as lmp FROM carrier\u prices WHERE SUBSTRING(拨号号码,1,长度(前缀))=前缀和承运人识别号=:承运人识别号按前缀顺序描述限制1
dialled_number
是子字符串函数sample data please-sqlfiddle.com(如果可能)中的值。公用表表达式?这可能不是你问题的答案,但如果你想匹配电话号码,你可能想使用前缀扩展名(),然后你可以编写更简单的查询,如“WHERE nr@>‘35567234567’”,以获取所有带有“3”、“355”、“35567”的条目。我很难格式化SO编辑框的查询。有些查询并不像我预期的那样结束。我问这个问题的原因是为了能够对单个运营商使用这个查询
从资费中选择trf_price,trf_prefix作为lmp,其中SUBSTRING(dialled_number,1,LENGTH(trf_prefix))=trf_prefix和trf_carrier_id=carrier_id ORDER BY trf_prefix DESC limit 1
,为所有运营商组合它们并在其上运行价格排序,因为它更具可读性。有什么想法吗?