2016-04-28 12 views
0

I持って、次の表:スカラ副問合せ

  1. table1 - session_idの、のcompany_id、session_start_time
  2. table2 - ID、SESSION_ID、MESSAGE_TIME、MESSAGE_TYPE、メッセージ
  3. table3 - company_id、company_name

table1には企業に対して行われたセッションが格納されます。各セッションには多くのメッセージがあり、これはtable2に格納されています。特定のmessage_type(例えばmessage_type = 2)については、メッセージから部分文字列を抽出する必要があります。この部分文字列は会社名です。これで、company_idがmessageとsession_start_time> = message_timeから抽出された会社名と一致するtable1から次のsession_idを見つける必要があります。

私は次のクエリを使用しています。

select t1.session_id as session1, 
     t1.company_id as company1, 
     @transfer_time := t2.message_time as transfer_time, 
     @company2 := trim(substring(t2.message, 38, locate(' abc', t2.message) - 38)) as company2, 
     (select t1.session_id 
     from table1 as t1 
      inner join table3 as t3 on t1.company_id = t3.company_id 
     where t1.session_start_time >= @transfer_time 
      and t3.company_name = @company2 
     order by t1.session_start_time 
     limit 1) as session 2 
from table1 as t1 
    inner join table2 as t2 on t1.session_id = t2.session_id 
    inner join table3 as t3 on t1.company_id = t3.company_id 
where t2.message_type = 2 

元のクエリは、さらにいくつかのスカラーサブクエリを持つと少し複雑です。このクエリは実行に非常に時間がかかります。私は説明関数でチェックし、スカラーサブクエリは実行に非常に時間がかかるようです。しかし、私はより良い方法を考えることができません。

+0

あなたはクエリのEXPLAINを投稿してください –

答えて

0

これはクエリです:

select t1.session_id as session1, t1.company_id as company1, 
     @transfer_time := t2.message_time as transfer_time, 
     @company2 := trim(substring(t2.message, 38, locate(' abc', t2.message) - 38)) as company2, 
     (select t1.session_id 
     from table1 t1 inner join 
      table3 t3 
      on t1.company_id = t3.company_id 
     where t1.session_start_time >= @transfer_time and 
       t3.company_name = @company2 
     order by t1.session_start_time 
     limit 1 
     ) s session 2 
from table1 t1 inner join 
    table2 t2 
    on t1.session_id = t2.session_id inner join 
    table3 t3 
    on t1.company_id = t3.company_id 
where t2.message_type = 2; 

まず、変数の使用が正しくありません。 MySQLはSELECTの変数の評価順序を保証しません。だから、あなたは、元の定義に置く必要があります。

select t1.session_id as session1, t1.company_id as company1, 
     t2.message_time as transfer_time, 
     trim(substring(t2.message, 38, locate(' abc', t2.message) - 38)) as company2, 
     (select t1.session_id 
     from table1 t1 inner join 
      table3 t3 
      on t1.company_id = t3.company_id 
     where t1.session_start_time >= t2.message_time and 
       t3.company_name = trim(substring(t2.message, 38, locate(' abc', t2.message) - 38)) 
     order by t1.session_start_time 
     limit 1 
     ) s session 2 
from table1 t1 inner join 
    table2 t2 
    on t1.session_id = t2.session_id inner join 
    table3 t3 
    on t1.company_id = t3.company_id 
where t2.message_type = 2; 

次に、私はインデックスをしようと:table3(company_name, company_id)table1(company_id, session_start_time, session_id)