2017-02-23 5 views
1

test_3,test_2およびtest_1の3つの表の間に結合があります。GROUP BYでCLOBデータを呼び出す

test_1およびtest_3はメインテーブルであり、共通の列はありません。テーブルtest_2によって結合されています。 test_1sr_idlast_updated_date
test_2sr_idsm_idを持っており、test_3sm_idsql_statementを持っています。 test_3には、すべての問題を引き起こすデータがあります。

最新のsr_idsm_idに関連付けられていることを確認する必要があります。私の考えは集計関数max(last_updated_date)を使用し、それをグループ化することでした。 それはいろいろな理由で起こりません。

  1. この列には、sql_statementというCLOBデータが含まれています。

  2. 私は慣れていない結合を使用しました。

任意のアイデアが参考になります。

WITH xx as (
    (select ANSWER ,sr_id AS ID from test 
    WHERE Q_ID in (SELECT Q_ID FROM test_2 WHERE field_id='LM_LRE_Q6') 
    ) 
) 
-- end of source data 


SELECT t.ID, t1.n, t1.SM_ID,seg_dtls.SEGMENTation_NAME ,to_char(mst.LAST_UPDATED_DATE,'dd-mon-yyyy hh24:mi:ss'),seg_dtls.sql_statement 
FROM xx t 
CROSS JOIN LATERAL (
     select LEVEL AS n, regexp_substr(t.answer, '\d+', 1, level) as SM_ID 
     from dual 
     connect by regexp_substr(t.answer, '\d+', 1, level) IS NOT NULL 
) t1 
left join test_1 mst 
on mst.sr_id=t.id 
right join test_3 seg_dtls 
on seg_dtls.sm_id=t1.sm_id; 

サンプルデータが

sr_id sm_id SEGMENTATION_NAME LAST_UPDATED_DATE 
1108197 958 test_not_in   05-feb-2017 23:56:59  
1108217 958 test_not_in   14-feb-2017 00:37:39 
1108218 958 test_not_in   14-feb-2017 01:39:50 
1108220 958 test_not_in   14-feb-2017 03:39:07 

のようになりますと予想される出力は、それが巨大であるので、私はCLOBデータを掲載していません

1108220 958 test_not_in   14-feb-2017 03:39:07 

です。 すべての行にはCLOBデータが含まれています。

table test_3 contains 
q_id  sr_id answer 
1009330 1108246 976~feb_24^941~Test_regionwithcountry 
1009330 1108247 941~Test_regionwithcountry_2016^787~Test_Request_28^976~feb_24 
1009330 1108239 972~test_emea 
1009330 1108240 972~test_emea^827~test_with_region_country 
1009330 1108251 981~MSE100579729 testing. 

とサンプルデータは、上記のtest_3
回答SM_IDが含まれていますように見えます。私はここからそれを抜き取る必要があります。例えば

941~Test_regionwithcountry_2016^787~Test_Request_28^976~feb_24 
the sm_id is 941,787,976 

私は上記の質問を投稿しました。
もう一度、左と右のジョインに来ると、ここで正しい結合を使用するために、test_3からのすべてのsm_idが必要です。

edit1:受け入れられる答えは、最大(last_updated_date)のSR_ID OF SEGMENTSを与えます。
すべてのSR_IDが必要です。そこで、MINUS演算子を使ってmax(last_updated_date)でないものを取得しました。
私はその結果セットを受け入れられた回答に追加する必要があります。

これは私が他のSR_IDを取得するために行ったことです。

select sr_id,segmentation_name,request_status from (with test_31 (q_id, sr_id, answer) as (
(SELECT Q_ID,SR_ID,ANSWER FROM test_3 WHERE Q_ID=(SELECT Q_ID FROM test_4 WHERE FIELD_ID='LM_LRE_Q6')) 
), 
answer_extraction as (
    select q_id, sr_id, 
    regexp_substr(regexp_substr(answer, '[^^]+', 1, level),'\d+') as sm_id 
    from test_31 
    connect by q_id = prior q_id 
    and sr_id = prior sr_id 
    and prior dbms_random.value is not null 
    and regexp_substr(answer, '[^^]+', 1, level) is not null 
) 
select sr_id, 
    sm_id, 
    segmentation_name, 
    LAST_UPDATED_DATE, 
    sql_statement,request_status 
from (
    select t1.sr_id, 
    t2.sm_id, 
    t2.segmentation_name, 
    t1.last_updated_date, 
    t2.sql_statement, 
    t1.request_status 

    from test_4 t4 
    join answer_extraction t3 on t3.q_id = t4.q_id 
    join test_2 t2 on t2.sm_id = t3.sm_id 
    join test1 t1 on t1.sr_id = t3.sr_id 
) 
) 
minus 

(select sr_id,segmentation_name , request_status from (with test_31 (q_id, sr_id, answer) as (
(SELECT Q_ID,SR_ID,ANSWER FROM test_3 WHERE Q_ID=(SELECT Q_ID FROM test_4 WHERE FIELD_ID='LM_LRE_Q6')) 
), 
answer_extraction as (
    select q_id, sr_id, 
    regexp_substr(regexp_substr(answer, '[^^]+', 1, level), '\d+') as sm_id 
    from test_31 
    connect by q_id = prior q_id 
    and sr_id = prior sr_id 
    and prior dbms_random.value is not null 
    and regexp_substr(answer, '[^^]+', 1, level) is not null 
) 
select sr_id, 
    segmentation_name, 
    sql_statement, 
    request_status 
from (
    select t1.sr_id, 
    t2.sm_id, 
    t2.segmentation_name, 
    t1.last_updated_date, 
    t2.sql_statement, 
    t1.request_status, 
    max(t1.last_updated_date) over (partition by t2.sm_id) as max_updated_date 
    from test_4 t4 
    join answer_extraction t3 on t3.q_id = t4.q_id 
    join test_2 t2 on t2.sm_id = t3.sm_id 
    join test_1 t1 on t1.sr_id = t3.sr_id 
) 
where last_updated_date = max_updated_date)); 

}

サンプルデータ:
受け入れ答えは、セグメントの最大(last_updated_date)と出力下に与えます。掲載クエリ上記

1097661 Submitted o2k lad 30-NOV-15 01-DEC-16 62 CLOB DATA 

他の更新日付とセグメントのSR_IDある出力の下に与えるものです。

1097621 o2k lad Submitted 
    1097625 o2k lad Submitted 
    1097627 o2k lad Submitted 
    1097632 o2k lad Submitted 
    1097633 o2k lad Submitted 
    1097658 o2k lad Pending 
    1097640 o2k lad Submitted 
    1097644 o2k lad Submitted 
    1097646 o2k lad Submitted 

予想される出力:

sr_id status  segment_name updated_date sql_statement other_sr_id 
1097661 Submitted o2k lad  30-NOV-15  CLOB DATA 1097618,1097621,1097625,1097627,1097632,1097633,1097658,1097640,1097644,1097646 

最後の列は、すべての古いSR_IDを含むように、2つのクエリを兼ね備えています。

+0

サンプル入力データと期待される出力を投稿してください。それは本当にすべてのユーザーに役立つでしょう。 – Tajinder

+1

'max(last_updated_date) 'を使用する当初の計画は、あなたの質問のコードよりもはるかに有望です。多分あなたは再び始めるべきです。 –

+0

私は知っていますが、すべての列が必要です。clobを含むものもあります。 – user3165555

答えて

0

かなり単純なオプションのようなものとして、各IDの最大の日付を見つけ、分析機能を追加するために、あなたの現在のクエリを変更することです:

..., max(mst.last_updated_date) over (partition by id) as max_updated_date 

一般的なアイデアの迅速なデモ:

with cte (id, last_updated_date, sql_statement) as (
    select 1, date '2017-01-01', to_clob('stmt 1') from dual 
    union all select 1, date '2017-01-02', to_clob('stmt 2') from dual 
    union all select 1, date '2017-01-03', to_clob('stmt 3') from dual 
    union all select 2, date '2017-01-02', to_clob('stmt 4') from dual 
) 
select id, last_updated_date, sql_statement 
from (
    select id, last_updated_date, sql_statement, 
    max(last_updated_date) over (partition by id) as max_updated_date 
    from cte 
) 
where last_updated_date = max_updated_date; 

     ID LAST_UPDAT SQL_STATEMENT                 
---------- ---------- -------------------------------------------------------------------------------- 
     1 2017-01-03 stmt 3                   
     2 2017-01-02 stmt 4                   

row_number()またはrank()またはdense_rank()を使用して、最古の日付とフィルタを持つ行を識別できますが、一般的な考え方は同じです。

ただし、現在のクエリはあまり明確ではありません(または12cより前に有効です)。このような関数とフィルタをどのように含めるかを推測するのではなく、元のテーブルからやり直すほうが簡単でしょうが、これはあなたが何をしているかを前提にしています。実際に必要とされるかもしれません。 CTEを経由して、いくつかのデータをバックアップ作成

with test_1 (sr_id, last_updated_date) as (
    select 1108197, timestamp '2017-02-05 23:56:59' from dual 
    union all select 1108217, timestamp '2017-02-14 00:37:39' from dual 
    union all select 1108218, timestamp '2017-02-14 01:39:50' from dual 
    union all select 1108220, timestamp '2017-02-14 03:39:07' from dual 
), 
test_2 (sm_id, segmentation_name, sql_statement) as (
    select 958, 'test_not_in', to_clob('select * from dual') from dual 
), 
test_3 (q_id, sr_id, answer) as (
    select 41, 1108197, 958 from dual 
    union all select 42, 1108217, 958 from dual 
    union all select 43, 1108218, 958 from dual 
    union all select 44, 1108220, 958 from dual 
), 
test_4 (q_id, field_id) as (
    select 41, 'LM_LRE_Q6' from dual 
    union all select 42, 'LM_LRE_Q6' from dual 
    union all select 43, 'LM_LRE_Q6' from dual 
    union all select 44, 'LM_LRE_Q6' from dual 
) 

が、これはあなたが疑問に示した同じ出力を取得:右に近い野生の前提として

select t1.sr_id, 
    t2.sm_id, 
    t2.segmentation_name, 
    to_char(t1.last_updated_date, 'dd-mon-yyyy hh24:mi:ss') as last_updated_date, 
    t2.sql_statement 
from test_4 t4 
join test_3 t3 on t3.q_id = t4.q_id 
join test_2 t2 on t2.sm_id = t3.answer 
join test_1 t1 on t1.sr_id = t3.sr_id; 

    SR_ID SM_ID SEGMENTATIO LAST_UPDATED_DATE    SQL_STATEMENT                 
---------- ----- ----------- ----------------------------- -------------------------------------------------------------------------------- 
    1108197 958 test_not_in 05-feb-2017 23:56:59   select * from dual                
    1108217 958 test_not_in 14-feb-2017 00:37:39   select * from dual                
    1108218 958 test_not_in 14-feb-2017 01:39:50   select * from dual                
    1108220 958 test_not_in 14-feb-2017 03:39:07   select * from dual                

を、あなたは見つけることができます各最新の日付はsm_idのようになります。

明確ではない他の制限や要件(例えば、左右の外部結合を含む)に対処するには、それを適応させる必要があります。

「回答」を複数の値に分割するために行っていたサブクエリを意図的に無視しました。データモデルの問題であるIDの区切られたリストのような恐ろしいものがある可能性があります。その場合は、依然として個々のsm_id値を抽出する必要があります。以下のようなもの:あなたが追加test3の実際の内容に基づいて


with answer_extraction as (
    select q_id, sr_id, regexp_substr(answer, '\d+', 1, level) as sm_id 
    from test_3 
    connect by q_id = prior q_id 
    and sr_id = prior sr_id 
    and prior dbms_random.value is not null 
    and regexp_substr(answer, '\d+', 1, level) is not null 
) 
select sr_id, 
    sm_id, 
    segmentation_name, 
    to_char(last_updated_date, 'dd-mon-yyyy hh24:mi:ss') as last_updated_date, 
    sql_statement 
from (
    select t1.sr_id, 
    t2.sm_id, 
    t2.segmentation_name, 
    t1.last_updated_date, 
    t2.sql_statement, 
    max(t1.last_updated_date) over (partition by t2.sm_id) as max_updated_date 
    from test_4 t4 
    join answer_extraction t3 on t3.q_id = t4.q_id 
    join test_2 t2 on t2.sm_id = t3.sm_id 
    join test_1 t1 on t1.sr_id = t3.sr_id 
) 
where last_updated_date = max_updated_date; 
は、あなたの正規表現は、あなたが必要なものをかなりやっていません。使用しているパターンでは、14個の数値が見つかります。任意の数字:

with test_3 (q_id, sr_id, answer) as (
    select 1009330, 1108246, '976~feb_24^941~Test_regionwithcountry' from dual 
    union all select 1009330, 1108247, '941~Test_regionwithcountry_2016^787~Test_Request_28^976~feb_24' from dual 
    union all select 1009330, 1108239, '972~test_emea' from dual 
    union all select 1009330, 1108240, '972~test_emea^827~test_with_region_country' from dual 
    union all select 1009330, 1108251, '981~MSE100579729 testing.' from dual 
), 
answer_extraction as (
    select q_id, sr_id, regexp_substr(answer, '\d+', 1, level) as sm_id 
    from test_3 
    connect by q_id = prior q_id 
    and sr_id = prior sr_id 
    and prior dbms_random.value is not null 
    and regexp_substr(answer, '\d+', 1, level) is not null 
) 
select * from answer_extraction; 

     Q_ID  SR_ID SM_ID  
---------- ---------- ---------- 
    1009330 1108239 972  
    1009330 1108240 972  
    1009330 1108240 827  
    1009330 1108246 976  
    1009330 1108246 24   
    1009330 1108246 941  
    1009330 1108247 941  
    1009330 1108247 2016  
    1009330 1108247 787  
    1009330 1108247 28   
    1009330 1108247 976  
    1009330 1108247 24   
    1009330 1108251 981  
    1009330 1108251 100579729 

デリミタと〜マーカーの間のビットだけが必要なようです。区切られた文字列を分割する一般的な方法は次のとおりです。

with test_3 (q_id, sr_id, answer) as (
    select 1009330, 1108246, '976~feb_24^941~Test_regionwithcountry' from dual 
    union all select 1009330, 1108247, '941~Test_regionwithcountry_2016^787~Test_Request_28^976~feb_24' from dual 
    union all select 1009330, 1108239, '972~test_emea' from dual 
    union all select 1009330, 1108240, '972~test_emea^827~test_with_region_country' from dual 
    union all select 1009330, 1108251, '981~MSE100579729 testing.' from dual 
), 
answer_extraction as (
    select q_id, sr_id, regexp_substr(answer, '[^^]+', 1, level) as sm_id 
    from test_3 
    connect by q_id = prior q_id 
    and sr_id = prior sr_id 
    and prior dbms_random.value is not null 
    and regexp_substr(answer, '[^^]+', 1, level) is not null 
) 
select * from answer_extraction; 

     Q_ID  SR_ID SM_ID         
---------- ---------- ---------------------------------------- 
    1009330 1108239 972~test_emea       
    1009330 1108240 972~test_emea       
    1009330 1108240 827~test_with_region_country    
    1009330 1108246 976~feb_24        
    1009330 1108246 941~Test_regionwithcountry    
    1009330 1108247 941~Test_regionwithcountry_2016   
    1009330 1108247 787~Test_Request_28      
    1009330 1108247 976~feb_24        
    1009330 1108251 981~MSE100579729 testing.    

などですが、最初の部分を取得する必要があります。あなたのオリジナルのパターンを借りて(他の人が利用可能です!):余分なregexp_substr()が選択リストにあるだけで

column sm_id format a10 
with test_3 (q_id, sr_id, answer) as (
    select 1009330, 1108246, '976~feb_24^941~Test_regionwithcountry' from dual 
    union all select 1009330, 1108247, '941~Test_regionwithcountry_2016^787~Test_Request_28^976~feb_24' from dual 
    union all select 1009330, 1108239, '972~test_emea' from dual 
    union all select 1009330, 1108240, '972~test_emea^827~test_with_region_country' from dual 
    union all select 1009330, 1108251, '981~MSE100579729 testing.' from dual 
), 
answer_extraction as (
    select q_id, sr_id, 
    regexp_substr(regexp_substr(answer, '[^^]+', 1, level), '\d+') as sm_id 
    from test_3 
    connect by q_id = prior q_id 
    and sr_id = prior sr_id 
    and prior dbms_random.value is not null 
    and regexp_substr(answer, '[^^]+', 1, level) is not null 
) 
select * from answer_extraction; 

     Q_ID  SR_ID SM_ID  
---------- ---------- ---------- 
    1009330 1108239 972  
    1009330 1108240 972  
    1009330 1108240 827  
    1009330 1108246 976  
    1009330 1108246 941  
    1009330 1108247 941  
    1009330 1108247 787  
    1009330 1108247 976  
    1009330 1108251 981  

お知らせ、ない接続-by文節。抽出物sm_idは依然として文字列です。 test_2.sm_idが数字の場合は、その選択リストの部分文字列のまわりでto_number()コールを追加します。

+0

ありがとうアレックス。すべてのあなたの前提がスポットである。問題の大部分はtest_3という表にあります。私はより理解のための質問を編集しています。 – user3165555

+0

@ user3165555 - あなたの答えの値は私が想定していたよりも元気です。あなたが実際に興味を持っている数字だけを抽出する方法をちょっと追加しました。私は^と〜の間にある数字です。改訂された 'answer_extraction' CTEを、元のコードの残りの部分と一緒に使うことができます。 –

+0

ありがとう、アレックス、私はこのプロセスで多くを学んだ。 – user3165555