2015-05-20 48 views
3

這是關於PostgreSQL中的COALESCE的問題。在當前視圖我使用 COALESCE搶在列表中的第NOT NULL值:如何使用coalesce或變體來提取多個值?

COALESCE(vw_header_to_node_13.subsetname, 
vw_header_to_node_12.subsetname, 
vw_header_to_node_11.subsetname, 
vw_header_to_node_10.subsetname, 
vw_header_to_node_9.subsetname, 
vw_header_to_node_8.subsetname, 
vw_header_to_node_7.subsetname, 
vw_header_to_node_6.subsetname, 
vw_header_to_node_5.subsetname, 
vw_header_to_node_4.subsetname, 
vw_header_to_node_3.subsetname, 
vw_header_to_node_2.subsetname, 
vw_header_to_node_1.subsetname, 
vw_header_to_node.subsetname, 
vw_header_to_node.setname) 
AS prctr1 

我剛剛被告知,而不是抓住僅僅是第一NOT NULL場,我現在需要搶第一NOT NULL場以及第一個NOT NULL字段後的以下2個字段。例如,如果vw_header_to_node_8.subsetname是第一個NOT NULL字段,我想要獲取vw_header_to_node_8.subsetname,vw_header_to_node_7.subsetname,& vw_header_to_node_6.subsetname。我知道這不是COALESCE正常工作的方式,但是有誰知道任何變化或方法可以實現這一點嗎?

+0

是否有必要在SQL中執行此操作?你可以簡單地選擇所有這些值,並使用應用程序代碼來確定使用哪個值? – Aaron

+1

第二個和第三個值可以爲零,或者零值應該排除在外? – klin

+0

該列表是第二個和第三個值的方式不會爲空值。 – user3329160

回答

3

如果所有空值應該從列表中排除,這種方法應該工作:

  1. 的列表轉換爲陣列,
  2. 從數組中刪除空值,所述陣列的
  3. 選擇三個第一元件。

實施例:

with test as (
    select 
     null::text  as v1, 
     'apple'::text as v2, 
     null::text  as v3, 
     'banana'::text as v4, 
     'pear'::text as v5) 

select a[1] val1, a[2] val2, a[3] val3 
from (  
    select 
     array_remove(
      array[v1, v2, v3, v4, v5], null) a 
    from test 
    ) alias 

val1 | val2 | val3 
-------+--------+------ 
apple | banana | pear 

如果第二和第三個值可以爲空,我們應該修剪從陣列的第一空值在步驟2 有Postgres裏沒有合適的功能,但是可以寫它自己。

create function array_ltrim_nulls(arr anyarray) 
returns anyarray language plpgsql immutable 
as $$ 
declare 
    i integer; 
    l integer = array_length(arr, 1); 
begin 
    for i in 1..l loop 
     if arr[i] is not null then 
      return arr[i:l]; 
     end if; 
    end loop; 
    return null; 
end $$; 

with test as (
    select 
     null::text  as v1, 
     'apple'::text as v2, 
     null::text  as v3, 
     'banana'::text as v4, 
     'pear'::text as v5) 

select a[1] val1, a[2] val2, a[3] val3 
from (  
    select 
     array_ltrim_nulls(
      array[v1, v2, v3, v4, v5]) a 
    from test 
    ) alias 

val1 | val2 | val3 
-------+------+-------- 
apple |  | banana  

,使用更簡便我已經添加了以下功能到我的一套標準的功能。也許這個功能對你最有用。函數參數的數量是可變的。您只需確保所有參數具有相同的類型。

create function array_coalesce (variadic arr anyarray) 
returns anyarray language sql immutable 
as $$ 
    select array_remove(arr, null); 
$$; 

select array_coalesce(null::text, 'apple', null, 'banana', 'pear') arr; 
     arr   
--------------------- 
{apple,banana,pear} 

select array_coalesce(null::int, 1, null, 2, 3, 4, null, 5) arr; 
    arr  
------------- 
{1,2,3,4,5} 

select (array_coalesce(null::int, 1, null, 2, 3, 4, null, 5))[1:3] arr; 
    arr  
------------- 
{1,2,3} 
+0

感謝您花時間回答此問題。這是目前在一個視圖中完成的,我創建了一個層次結構,我正在通過多個連接到同一個表上運行COALESCE。我不確定我是否可以在此做一個數組。我不需要創建一個表並將所有的值輸入到數組中嗎? – user3329160

+0

你不需要任何特殊的表格。您可以在查詢中使用數組,並且此數組的元素可以來自任何連接的表或視圖,例如, 'select array [view1.field2,view2.field2,table1.field3]' – klin

+0

好吧。我會試一試。這對我來說是相當先進的!感謝您花時間幫忙。 – user3329160