在物化视图中使用另一个物化视图

时间:2016-09-16 19:23:03

标签: sql postgresql

数据库引擎我正在使用:PostgreSQL 9.5.2

我正在尝试做什么

我的PostgreSQL中有以下两个物化视图:

1) state_vendors_mat_view

vendor_id    sol_id    states_list    total_revenue
---------    ------    -----------    -------------
1234         abc       CA, AZ         23000.00
5678         abc       TX, FL         12000.00
9012         def       AZ, TX         67000.00

2) interested_vendors_mat_view

sol_id    vendor_id    
------    ---------
abc       1234
def       5678

我正在尝试查询给定sol_id的 state_vendors_mat_view (例如“abc”);但是,我想知道,对于结果中的每个vendor_id,此vendor_id是否映射到 interested_vendors_mat_view 中的sol_id。如果它被映射,我想要一个布尔值为true;否则,我想要一个布尔值为false。

此外,我希望此查询尽可能高效。我不想对 state_vendors_mat_view 的结果中的每条记录的 interested_vendors_mat_view 运行选择。

期望的结果

例如,如果我希望所有供应商都有sol_id =“abc”,那么我希望结果如下:

vendor_id    is_interested   sol_id    states_list    total_revenue
---------    -------------   ------    -----------    -------------
1234         True            abc       CA, AZ         23000.00
5678         False           abc       TX, FL         12000.00

备注

  • vendor_id = 1234的记录在is_interested列中的布尔值为True,因为interested_vendors_mat_view具有映射1234和“abc”的记录。
  • vendor_id = 5678的记录在is_interested列中的布尔值为False,因为interested_vendors_mat_view没有映射5678和“abc”的记录。

我看过的问题

SQL我试过

SELECT 
 vendor_id, 
 CASE
    WHEN ((SELECT count(*) FROM interested_vendors_mat_view iv 
           WHERE sol_id = 'abc' and iv.vendor_id = state.vendor_id) = 0) 
    THEN false 
    ELSE true
 END AS is_interested,
 sol_id, 
 states_list,
 total_revenue
FROM state_vendors_mat_view state WHERE sol_id = 'abc';

为了尝试获得正确的行数,我也尝试过:

SELECT 
  state.vendor_id, 
  state.sol_id, 
  count(*)
FROM state_vendors_mat_view state 
 JOIN interested_vendors_mat_view iv ON (iv.vendor_id = state.vendor_id)
WHERE state.sol_id = 'abc' 
GROUP BY state.vendor_id, state.sol_id
  

这些都没有给我正确的解决方案。

非常感谢任何帮助。感谢。

2 个答案:

答案 0 :(得分:2)

考虑使用LEFT JOIN的条件列计算is_interested查询,避免任何子查询需求:

SELECT s.vendor_id, 
       CASE WHEN i.sol_id = 'abc' 
            THEN TRUE 
            ELSE FALSE 
       END AS is_interested, 
       s.sol_id, 
       s.states_list, 
       s.total_revenue
FROM state_vendors_mat_view s
LEFT JOIN interested_vendors_mat_view i
ON (s.sol_id = i.sol_id) AND (s.vendor_id = i.vendor_id)
WHERE s.sol_id = 'abc'

答案 1 :(得分:1)

我不确定为什么你的查询不起作用,但可能是因为子查询中的比较使用snid而不是sol_id(根据数据格式应该生成错误)在你的问题中)。

在任何情况下,查询都会更简单地使用exists表达:

SELECT sv.*,
       (exists (select 1
                from interested_vendors_mat_view iv
                where iv.vendor_id = sv.vendor_id and iv.sol_id = 'abc'
               )
       ) as is_interested
FROM state_vendors_mat_view sv
WHERE sv.sol_id = 'abc';