1

selectステートメントの結果を再利用するSQLステートメントを作成したい(sqlliteを使用しているため、関数、IFステートメントなどを使用できません)。これは現在のように見えます。

INSERT INTO search_email(many_fields, threadid) VALUES ('many_fields',
    CASE 
    WHEN
            (
                (SELECT COUNT(tableX.threadid) %threadIDquery% 
                ) > 0
            )
    THEN

                (SELECT tableX.threadid %threadIDquery% LIMIT 1)

    ELSE 
            0
    END
)

別の(ほぼ同じ)selectステートメントを作成する代わりに、最初のselectの結果を再利用したいと思います。

更新:私が何をしようとしているのか疑問に思っている人のために..クエリの完全版は次のとおりです。

INSERT INTO search_email(meta, subject, body, sender, tos, ccs, folder, threadid) VALUES ('meta1','subject1','body1','sender1', 'tos1',' ccs1','folder1',
    CASE 
    WHEN
            (
                (SELECT COUNT(search_email.threadID) FROM search_email 
                                                            WHERE search_email.subject MATCH '%query%'  AND 
                                                            (
                                                                (search_email.sender = '%sender' AND search_email.tos = '%receiver%')
                                                                OR 
                                                                (search_email.sender = '%receiver%' AND search_email.tos = '%sender%')
                                                            )
                ) > 0
            )
    THEN

            (SELECT search_email.threadID FROM search_email 
                                                        WHERE search_email.subject MATCH '%query%'  AND 
                                                        (
                                                            (search_email.sender = '%sender%' AND search_email.tos = '%receiver%')
                                                            OR 
                                                            (search_email.sender = '%receiver%' AND search_email.tos = '%sender%')
                                                        )  LIMIT 1
            )

    ELSE 
            //generate new thread ID
    END
)

基本的に、受信メールのメールスレッドがすでに存在するかどうかを調べようとしています。したがって、件名が一致するかどうかを確認し、一致する場合は、メールの送信者と受信者が(どちらの方向でも)一致するかどうかを確認します。 ..メールスレッドが存在する場合は、同じメールスレッドIDを挿入するだけです。それ以外の場合は、新しいスレッドIDを生成します。

アップデート2:明確にするために、単に入力を節約する(または読みやすくするなど)のではなく、sqlliteコンパイラが同じ検索を2回行うのを防ぐ方法を探しています。

更新3: threadIDが生成されたのではなくdbaseから取得された場合に、このステートメントが生成されたthreadIDを返す方法があるかどうか疑問に思っていました。答えはここにあります。

4

1 に答える 1

3

これは、クエリを構造化する別の方法です。

INSERT INTO search_email(meta, subject, body, sender, tos, ccs, folder, threadid)
    SELECT 'meta1', 'subject1', 'body1', 'sender1', 'tos1', 'ccs1', 'folder1',
            coalesce((SELECT search_email.threadID
                      FROM search_email 
                      WHERE search_email.subject MATCH '%query%' AND 
                            ((search_email.sender = '%sender%' AND search_email.tos = '%receiver%') OR
                             (search_email.sender = '%receiver%' AND search_email.tos = '%sender%')
                            )
                      LIMIT 1
                     ),
                     <generate new thread id here>
                    )

これは のselect代わりに を使用していvaluesます。条件に一致するスレッド ID を取得するか、一致しない場合は NULL を取得します。の 2 番目の句はcoalesce、最初の句が NULL の場合に実行されます。そこで新しい ID を生成できます。

このアプローチには問題があります。私には、スレッドを管理する Thread テーブルが必要なようです。ThreadId は、このテーブルで自動インクリメントされた ID である必要があります。その後、メール テーブルはこの ID を参照できます。つまり、データモデルをもっと細かく考える必要があると思います。

次のクエリは作業をクエリしませんが、スレッドをサブクエリに移動するというアイデアを提供します。

INSERT INTO search_email(meta, subject, body, sender, tos, ccs, folder, threadid)
    SELECT 'meta1', 'subject1', 'body1', 'sender1', 'tos1', 'ccs1', 'folder1',
            coalesce(t.threadID,
                     <generate new thread id here>
                    )
    from (SELECT search_email.threadID
          FROM search_email 
          WHERE search_email.subject MATCH '%query%' AND 
                ((search_email.sender = '%sender%' AND search_email.tos = '%receiver%') OR
                 (search_email.sender = '%receiver%' AND search_email.tos = '%sender%')
                )
          LIMIT 1
         ) t

これが機能しない理由は、from句が NULL 値を持つ 1 つの行ではなく行を返さないためです。したがって、必要なものを取得するには、次を使用できます。

    from (SELECT search_email.threadID
          FROM search_email 
          WHERE search_email.subject MATCH '%query%' AND 
                ((search_email.sender = '%sender%' AND search_email.tos = '%receiver%') OR
                 (search_email.sender = '%receiver%' AND search_email.tos = '%sender%')
                )
          union all
          select NULL
          order by (case when threadId is not null then 1 else 0 end) desc
          LIMIT 1
         ) t

これにより、スレッドがない場合に NULL 値が返されることが保証されます。

于 2012-12-27T14:58:20.577 に答える