2015-04-29 4 views
6

Rozważ skorzystanie z poniższego kodu. Typ enum_buysell zawiera tylko 2 wartości: buy i sell. Muszę po prostu uzyskać przeciwną wartość w niektórych przypadkach, ale kod wygląda brzydko, imho. Czy istnieje sposób na jej optymalizację? Myślałem, że w ogóle nie używam enum, np. zamiast tego jest to boolean, ale ten pomysł nie jest idealny, ponieważ powoduje, że dane same w sobie są mniej oczywiste.Postgres: Jak uzyskać następny element w zestawie enum?

select 
    datetime, 
    case 
    when account_id_active = p_account_id and direction = 'buy' then 'buy'::enum_buysell 
    when account_id_active = p_account_id and direction = 'sell' then 'sell'::enum_buysell 
    when account_id_passive = p_account_id and direction = 'buy' then 'sell'::enum_buysell 
    when account_id_passive = p_account_id and direction = 'sell' then 'buy'::enum_buysell 
    end as direction, 
    price, 
    volume 
from 
    deals 
where 
    account_id_active = p_account_id or 
    account_id_passive = p_account_id 
order by 
    datetime desc 
limit 
    10; 
+0

logicznych: enum jest fundamentalnie * * nieuporządkowana. – wildplasser

+0

@wildplasser, zasadniczo masz absolutną rację, ale to nie dotyczy postgres, - spójrz na [docs: 8.7.2. Zamawianie] (http://www.postgresql.org/docs/9.4/static/datatype-enum.html) –

Odpowiedz

3

Ponieważ nie ma funkcji uzyskiwania następnej wartości wyliczenia w PostgreSQL, należy zdefiniować ją samodzielnie.

create function next_buysell (e enum_buysell) 
returns enum_buysell 
as $$ 
begin 
    return (case when e='buy'::enum_buysell then 'sell'::enum_buysell 
       else 'buy'::enum_buysell 
      end); 
end 
$$ language plpgsql; 

Teraz można go używać tak:

postgres=# select next_buysell('sell'::enum_buysell); 
next_buysell 
-------------- 
buy 
(1 row) 

postgres=# select next_buysell('buy'::enum_buysell); 
next_buysell 
-------------- 
sell 
(1 row) 

A twoja wypowiedź CASE staje: Problem

case 
    when account_id_active = p_account_id then direction 
    when account_id_passive = p_account_id then next_buysell(direction) 
end as direction 
+0

dziękuję, wygląda lepiej, to na pewno, ale czy nie ma jakichś wad wydajności związanych z wykonywaniem jeszcze jednej funkcji, co w zasadzie robi to samo, co sam wpisany kod? Chodzi mi o to, że te dziwne odlewania z "varchar" do "enum_buysell" wciąż tam są, czy naprawdę nie da się ich uniknąć? –