2017-12-18 5 views
0

こんにちは私は単純な質問であると感じるが、それを把握することはできません。私は、別の列との関連で最大数を見つけようとしています。それをグループ化すると、値の1つが文字列であるという問題が発生します。私は実際には「テスト」の1に等しくなるようにしたいデータについては文字列SQLを許可する最大機能をオーバーライドしますか?

Name Value 
Nate 0 
Nate 1 
Jeff 2 
Nate 2 
Nate 'Test' 

私はここでMAX()関数を使用している場合しかし、私はなります:

Name Value 
Nate 'Test' 
Jeff 2 

を私は多分あればと思うことができます私は 'Test'を1として読んでからmax関数を使います。これはどうやって自分の定義にMAX()をオーバーロードします。

何か助けていただきありがとうございます。

+0

「値」のデータ型は何ですか? –

+0

*値のうちの1つは文字列にすることはできません。列のすべての値は文字列です。ちょうど数字だけで構成されているものもあります。 'Test'の前後に一重引用符を表示するのは少し混乱します(文字列の値に実際には一重引用符が含まれていない限り)。おそらく、そのデータに基づいてNateの最大値も2になると予想していますか?それは唯一の非数値の値であり、すべて数値の1桁の数字ですか? –

答えて

2

通常、混合データを文字列に格納するのは悪い考えです。

あなたはケース式で固定値に特定の文字列を変換することができます

select max(case when value = 'Test' then '1' else value end) from ... 

しかし、あなたはまだ文字列を扱っているので、あなたはおそらく防ぐために、数値に変換したい「10」のソート例えば ​​'2' の前に:

select max(to_number(case when value = 'Test' then '1' else value end)) from ... 

たり、SAのCTEを使用して

select max(case when value = 'Test' then 1 else to_number(value) end) from ... 

データ:

-- CTE for dummy data 
with your_table (name, value) as (
    select 'Nate', '0' from dual 
    union all select 'Nate', '1' from dual 
    union all select 'Jeff', '2' from dual 
    union all select 'Nate', '2' from dual 
    union all select 'Nate', 'Test' from dual 
) 
-- actual query 
select name, 
    max(case when value = 'Test' then 1 else to_number(value) end) as value 
from your_table 
group by name; 

NAME  VALUE 
---- ---------- 
Nate   2 
Jeff   2 

しかし、明示的または暗黙的に数値に変換できないすべての値をカバーする必要があります。

数値以外の値を無視する場合や、個々の文字列をそれぞれの数値にマッピングするのではなく、すべて同じ固定値として扱いたい場合は、やや簡単です。その後、任意の文字列を変換しようとする関数を書くことができ、例外が発生した場合はnull(またはその他の固定値)を返します。あなたは、おそらくオフより良い戻っておよび防ぐために、データモデルを再設計することだろう

with 
    function hack_to_number(string varchar2) return number is 
    begin 
    return to_number(string); 
    exception 
    when others then 
     return 1; 
    end; 
select name, 
    max(hack_to_number(value)) as value 
from your_table 
group by name; 

NAME  VALUE 
---- ---------- 
Nate   2 
Jeff   2 

:この臨時のものならば、あなたも、with a PL/SQL declarationではなく、恒久的なスタンドアロンまたはパッケージ化機能を行うことができます12cR1から

この種の問題は、正しいデータ型を使用することによって解決されます。


@DrYWitは、あなたも、あなたがそれを明示的に呼び出す場合the to_number() functionとして、これは、内蔵している、ことを行う必要はありません12cR2から、コメントで指摘したように:

select name, 
    max(to_number(value default 1 on conversion error)) as value 
from your_table 
group by name; 
+1

12cリリース2以降、このto_numberのような "on conversion error"パラメータを使用できます(変換エラーの場合は 'test' default 1)。 –

+0

はい、あなたが最初に言ったことは、私が持っていた問題はMAX()が結果に基づいて特定の日付フィールドを表現したかったということでした。私はcaseステートメントに固執しており、フロントエンドアプリケーションのデータをフィルタリングします。データ構造に関しては、私は同意しますが、それを制御することはできません:/。迅速な対応をありがとうございます。 – Bagbobilbins

+0

私は変換エラーでその修正が大好きですが、代わりにその可能性があります。ありがとうございました! – Bagbobilbins

0

方法についてこの正規表現は「トリック」ですか?

SQL> with your_table (name, value) as (
    2 select 'Nate', '0' from dual 
    3 union all select 'Nate', '1' from dual 
    4 union all select 'Jeff', '2' from dual 
    5 union all select 'Nate', '2' from dual 
    6 union all select 'Nate', 'Test' from dual 
    7 ) 
    8 select name, max(to_number(value)) mv 
    9 from your_table 
10 where regexp_like (value, '^\d+$') 
11 group by name; 

NAME   MV 
---- ---------- 
Nate   2 
Jeff   2 

SQL> 
関連する問題