2

次の3つのテーブルがあります

Table1

ID |   NAME
-----------
1  | X
2  | Y
3  | Z


Table2

ID |   NAME
-----------
1  | A
2  | B
3  | C

Table3
ID | P (Boolean field)  | Other cols
 1 | True ...
 2 | True....
 1 | False

ここで、次のことを行う必要がある table3 に対するクエリが必要です。

table1 と table2 の名前フィールドを表示します。しかし、私の問題は、table3 のフィールド P が true の場合、table2.id = table3.id の table2 のフィールドの名前を表示したいのですが、false の場合は、table1.id の table1 の名前フィールドの名前を読み取る必要があることです。 = table3.id.

結果を表示するプログラムはデスクトップアプリケーションであり、それらを表示するための手順または何かを使用して実行できますが、これを実行するための SQL クエリがあればもっと良いでしょう。

4

5 に答える 5

3

これ:

SELECT  CASE WHEN p
        THEN
        (
        SELECT  name
        FROM    table2 t2
        WHERE   t2.id = t3.id
        ) 
        ELSE
        (
        SELECT  name
        FROM    table1 t1
        WHERE   t1.id = t3.id
        )
        END
FROM    table3 t3

、またはこれ:

SELECT  CASE WHEN p THEN t2.name ELSE t1.name END
FROM    table3 t3
JOIN    table1 t1
ON      t1.id = t3.id
JOIN    table1 t2
ON      t2.id = t3.id

HASH JOINを実行できる(つまりOracleSQL Server、を実行PostgreSQLできない)システムではMySQL、ブール値が均等に分散されている場合、つまり と が両方とも多数存在し、 が非常に大きい場合は、2 番目の方法が適してTRUEいますFALSEtable3

table3分布に偏りがある場合、table1またはの行数がはるかに少ないtable2場合、または を使用している場合は、最初のものの方が適していますMySQL

アップデート:

フィールドの大部分が false の場合、次のクエリがおそらく最適です。

SELECT  CASE WHEN p THEN
        (
        SELECT  name
        FROM    table2 t2
        WHERE   t2.id = t3.id
        )
        ELSE t1.name
        END AS cname
FROM    table3 t3
JOIN    table1 t1
ON      t1.id = t3.id
ORDER BY
        cname

ここでのサブクエリはフォールバックとしてのみ使用され、まれなTRUE値に対してのみ実行されます。

更新 2:

Firebird では確認できませんが、ほとんどのシステムでは、ORDER BY上記のクエリのような構文が機能します。そうでない場合は、クエリをインライン ビューにラップします。

SELECT  cname
FROM    (
        SELECT  CASE WHEN p THEN
                (
                SELECT  name
                FROM    table2 t2
                WHERE   t2.id = t3.id
                )
                ELSE t1.name
                END AS cname
        FROM    table3 t3
        JOIN    table1 t1
        ON      t1.id = t3.id
        ) q
ORDER BY
        cname

、パフォーマンスを妨げる可能性がありますが(少なくともMySQLそうです)。

于 2009-07-17T12:24:13.093 に答える
1

あなたが使用することができます

select if(P, t1.name, t2.name) ...
于 2009-07-17T12:24:35.480 に答える
0

おそらくオプションではありませんが、スキーマの再設計によって多くの問題が解決される場合があります。行ごとの関数を実行するソリューションは、パフォーマンスの問題について非常に注意深く調べる必要があります(実際には、パフォーマンスの問題、特に行ごとの関数の問題について、クエリを継続的に監視する必要があります)

したがって、表1と表2を組み合わせることを検討してください。

Table1And2:
    Id | IsTable2 | Name
    ---+----------+-----
    1  | false    | X
    2  | false    | Y
    3  | false    | Z
    1  | true     | A
    2  | true     | B
    3  | true     | C
    Primary key (Id,IsTable2)
    Possible index on (IsTable2) as well, depending on DBMS.

Table3:
    Id | P (Boolean field)  | OtherCols
    ---+--------------------+----------
     1 | true               |
     2 | true               |
     1 | false              |

次に、クエリは比較的単純になります(そして、ほぼ確実に目がくらむほど高速になります)。

select a.Id, b.Name, a.OtherCols
from Table3 a, Table1And2 b
where a.Id = b.Id and a.P = b.isTable2

パフォーマンスの問題は通常、500万行が構成テーブルと見なされるメインフレームサイズの大きなテーブルにのみ頭を悩ませます:-)扱っているテーブルの種類には必要ないかもしれませんが、武器庫。

于 2009-07-17T12:39:20.990 に答える
0
SELECT `id`, IF(`table3`.`P`, `table2`.`name`, `table1`.`name`) AS `name`
FROM `table3`
JOIN `table2` USING (`id`)
JOIN `table1` USING (`id`)
于 2009-07-17T12:25:57.227 に答える